Reputation: 4987
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
.
Upvotes: 0
Views: 78
Reputation: 25966
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 idealT extends any
).
Upvotes: 1