DEV Community

Acid Coder
Acid Coder

Posted on • Updated on

Typescript Generate Full Path Type And Get Value Type Of Nested Union Object With Numeric Key

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]
Enter fullscreen mode Exit fullscreen mode

Image description

support:

  1. nested
  2. numeric keys
  3. unions

playground

There is one serious flaw, do you know what it is and how to fix it? (hint: collapsing path)

Top comments (4)

Collapse
 
martinragan profile image
Martin Ragan

type XD = {x: string} | {b: number}; is giving incorrect output by your type in my opinion

Collapse
 
tylim88 profile image
Acid Coder

ya, it does not work with top level unions because

type I = keyof ({x: string} | {b: number})
//   ^? never
Enter fullscreen mode Exit fullscreen mode
Collapse
 
martinragan profile image
Martin Ragan

This can be solvable easily. But recursive types are cryptonit for this.

Thread Thread
 
tylim88 profile image
Acid Coder • Edited

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