In reference to this question, the previous structure had a depth of 2:
const grandkids = {
Karen: {
Ava: ['Alice', 'Amelia'],
Emma: ['Sarah'],
},
Mary: {
Sophia: ['Grace'],
},
} as const;
To extract literal types from the example above, you can use:
type Grandmother = keyof typeof grandkids; // Karen|Mary
type Mother = {
[K in Grandmother]: keyof typeof grandkids[K];
}[Grandmother]; // Ava|Emma|Sophia
type Kid = {
[K in Grandmother]: {
[M in Mother]: typeof grandkids[K][M extends keyof typeof grandkids[K] ? M : never];
};
}[Grandmother][Mother][number]; // Alice|Amelia|Sarah|Grace
But what about structures with 3 levels?
const greatgrandkids = {
Beth: {
Karen: {
Ava: ['Alice', 'Amelia'],
Emma: ['Sarah'],
},
Mary: {
Sophia: ['Grace'],
},
},
Ruth: {
Ella: {
Scarlett: ['Charlotte'],
},
},
};
For the structure above, which includes a great-grandmother, there is an additional type for the first level:
type GreatGrandmother = /* CODE?? */; // Beth|Ruth
type Grandmother = ... ; // Karen|Mary|Ella
type Mother = // ...
This pattern continues for any number of levels. Ensuring consistent depth with complete levels down to the leaf fields is important.