I have a constant which is a tree holding unique keys as its leaves, e.g.:
const Tree = {
Branch1: {
Leaf1: '1'
SubBranch1: {
SubLeaf: '11'
},
...
},
Branch2: {
Leaf2: '2'
SubBranch2: {
SubLeaf: '21'
}
},
...
}
I would like to create a generic type Leaves<typeof Tree>
that would be a list of all of the leaf values, i.e. '1' | '11' | '2' | '21' ...
. The issue is that I cannot find any examples of how I can effectively reduce a tree of objects to their keys or anything of the sort.
CodePudding user response:
You may use
const Tree = {
Branch1: {
Leaf1: '1',
SubBranch1: {
SubLeaf: '11'
}
},
Branch2: {
Leaf2: '2',
SubBranch2: {
SubLeaf: '21'
}
}
} as const;
type Leaves<T, L0 = T[keyof T]> = L0 extends Record<string, any> ? Leaves<L0> : L0;
let l: Leaves<typeof Tree>
// ^?let l: "1" | "11" | "2" | "21"
The only thing worth explaining is the fact that the type parameter L0
may be a conditional type (if there are multiple keys) so in that case it works as a distributive conditional type.
Also, using as const
(const assertion) when defining the constant ensures its type is the most specific case, otherwise the leaves types would have been just string
.
Note: edited to remove unnecessary code. The original playground might still be useful to understand how it works.