0
const program = {
  morgning: ['breakfast', 'mingle'],
  evning: ['mingle', 'eat', 'party']
} as const

const namespaceEvent = Object.entries(program).reduce(
  (acc, [namespace, events]) => [...acc, ...events.map(event => `${namespace}.${event}`)],
  [] as string[]
) // can't do 'as const' here;

type Namespace = typeof namespaceEvent[number] // sees the type as 'string' and not "morgning.breakfast" | "morgning.mingle" | "evning.mingle" | "evning.eat" | "evning.party"

const test: Namespace = 'foo.bar' // would like this to error

console.log(namespaceEvent) // ["morgning.breakfast", "morgning.mingle", "evning.mingle", "evning.eat", "evning.party"] 

How do I make this work and why doesn't it work?

Norfeldt
  • 8,272
  • 23
  • 96
  • 152
  • Does this answer your question? [Typescript Key-Value relation preserving Object.entries type](https://stackoverflow.com/questions/60141960/typescript-key-value-relation-preserving-object-entries-type) – Aplet123 Nov 25 '21 at 12:03
  • Also, this seems like a good use of `flatMap` isntead of `reduce`. – Aplet123 Nov 25 '21 at 12:03
  • @Aplet123 I'm very open for suggestions - could you share a code example? – Norfeldt Nov 25 '21 at 13:03

1 Answers1

2

I think this is an approach to solve this:

A lot more convoluted than what I thought, there may be a better approach!

const program = {
  morgning: ['breakfast', 'mingle'],
  evning: ['mingle', 'eat', 'party']
} as const

type KV = {[K in keyof typeof program]: `${K}.${typeof program[K][number]}`};
type NS = KV[keyof KV];
// type NS = "morgning.breakfast" | "morgning.mingle" | "evning.mingle" | "evning.eat" | "evning.party"

const namespaceEvent = Object.entries(program).reduce(
  (acc, [namespace, events]) => [...acc, ...events.map(event => `${namespace}.${event}`)] as NS[],
  [] as NS[]
) 


const test: NS = 'foo.bar' // ERROR: Type '"foo.bar"' is not assignable to type 'NS'.
const test1: NS = 'morgning.breakfast' // works


console.log(namespaceEvent) // ["morgning.breakfast", "morgning.mingle", "evning.mingle", "evning.eat", "evning.party"] 

See TS Playground: https://tsplay.dev/WJRV5W

Nishant
  • 54,584
  • 13
  • 112
  • 127
  • 3
    [Here's a version using `flatMap`](https://tsplay.dev/w2E2zW). The typing is the same but the implementation is a bit shorter. – Aplet123 Nov 25 '21 at 13:08
  • Nice work @Aplet123 thanks for sharing. I tend to use reduce, but this is much cleaner – Norfeldt Nov 25 '21 at 13:15