Before TS 4.8, obtaining value type for path A/${number}
of { A: Record<number, boolean> }
is possible, that is type B = DeepValue<A/${number}> // boolean
however it is impossible to get the value type for path A/${123}
of { A: { 123: boolean } }
, type B = DeepValue<A/${123}> // never
With TS 4.8, Improved Inference for infer Types in Template String Types made numeric literal path type possible
type DeepKey<
T,
K extends keyof T = keyof T
> = K extends string | number
? T[K] extends infer R
? `${K}`| (R extends Record<string, unknown> ? `${K}/${DeepKey<R>}` : never)
: never // impossible route
: never // impossible route
type DeepValue<
T,
P extends DeepKey<T>,
> = P extends `${infer K}/${infer Rest}`
? T[(K extends `${infer R extends number}` ? R : K) & keyof T] extends infer S
? S extends never // make S distributive to work with union object
? never
: Rest extends DeepKey<S>
? DeepValue<S, Rest>
: never // impossible route
: never // impossible route
: T[(P extends `${infer R extends number}` ? R : P) & keyof T]
support:
- nested
- numeric keys
- unions
There is one serious flaw, do you know what it is and how to fix it? (hint: collapsing path)
Top comments (4)
type XD = {x: string} | {b: number}; is giving incorrect output by your type in my opinion
ya, it does not work with top level unions because
This can be solvable easily. But recursive types are cryptonit for this.
It is, but this is not the flaw that in my mind. The flaw is more specific to this case, not to recursive type in overall