0

I have data structure similar to:

const Data = {
    key1: {
        key1a: '1a',
        key1b: '1b',
    },
    key2: {
        key2a: '2a',
        key2b: '2b',
    },
    keyN: {
        keyNa: 'Na',
        keyNb: 'Nb',
    },
}

And I want to generate a type for the list of all subkeys like this:

type DataSubkeysV1 = 'key1a' | 'key1b' | 'key2a' | 'key2b' | 'keyNa' | 'keyNb';
type DataSubkeysV2 = keyof typeof Data['key1'] | keyof typeof Data['key2'] | keyof typeof Data['keyN'];

How to write a type definition for any number of top-level keys?

I've tried a generic type:

type DataSubkeysV3<K extends keyof typeof Data> = keyof typeof Data[K]

But it requires an argument. And I want a type that can be used like DataSubkeysV1.

1 Answer 1

1
type UnionKeys<T> = T extends any ? keyof T : never
type FirstLevelValues<T> = T[keyof T]
type SecondLevelKeys<T> = UnionKeys<FirstLevelValues<T>>
type MyKeys = SecondLevelKeys<typeof Data>
// type MyKeys = "key1a" | "key1b" | "key2a" | "key2b" | "keyNa" | "keyNb"

See Checking for union type for the rationale of UnionKeys

we must first get a union of all the keys from all union constituents. To do this we must use the distributive behavior of conditional types. Using this behavior we can build a type that extracts extracts the keys of each union constituent and creates a union of all. To trigger the distributive behavior we can use an always true condition ( T extends T, T extends unknown or, less ideal T extends any).

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.