Home > Enterprise >  How to use the values of a nested object as a TypeScript type
How to use the values of a nested object as a TypeScript type

Time:11-18

The question

Having the following object:

const categories = {
  foo1: {
    bar1: "baz1"
  },
  foo2: {
    bar2: "baz2"
  }
} as const

How could I dynamically use baz1 and baz2 as the accepted values, as so:

type Item = {
  categories: Array<'baz1' | 'baz2'>
}

What I've done

I've managed to put together the following utils:

type Join<K, P> = K extends string | number
    ? P extends string | number
        ? `${K}${'' extends P ? '' : '.'}${P}`
        : never
    : never

type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, ...0[]]

type Leaves<T, D extends number = 10> = [D] extends [never]
    ? never
    : T extends object
    ? { [K in keyof T]-?: Join<K, Leaves<T[K], Prev[D]>> }[keyof T]
    : ''

Which allow me to do the following:

type CategoryKeys = Leaves<typeof categories> // `foo1.bar1`, `foo2.bar2`

The problem

But the problem is that this won't work:

type CategoryValues = typeof categories[CategoryKeys] // ❌
// or
type CategoryValues = typeof categories['foo1.bar1'] // ❌

Because what would actually work, afaik, is:

type CategoryValues = typeof categories['foo1']['bar1'] // `baz1`

Thank you!

CodePudding user response:

If you want just a union of all existed values, you can check this:

const categories = {
    foo1: {
        bar1: "baz1"
    },
    foo2: {
        bar2: "baz2"
    }
} as const

type Primitives = string | number | symbol;

type Values<T> = T[keyof T]

type ValuesUnion<T, Cache = T> =
    T extends Primitives ? T : Values<{
        [P in keyof T]:
        | Cache | T[P]
        | ValuesUnion<T[P], Cache | T[P]>
    }>

type Result = ValuesUnion<typeof categories>

Playground

CodePudding user response:

As @captain-yossarian-from-ukraine suggested, this playground has the answer.

In type Result, I just had to replace 'foo2.bar2' with AllKeys and it works as needed.

Thank you!

  • Related