1

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!

2

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.