Typescript extract type from object by object path in tuple

Viewed 711

Is it possible to extract type form object providing a path to it in N size tuple format. If so, how? Example what I have in mind:

type ExtractType<O, T> = ...;
type Foo = ExtractType<{ a: { b: number } }, ['a', 'b']> // I expect Foo type to be number
2 Answers

Below naive version, naive it means I don't restrict path to be valid path of the object, if keys path is invalid the return type will be unknown.

type ExtractType<O, T extends Array<any>> = {
  [K in keyof O]:
    ((...a: T) => any) extends ((a: any, ...args: infer Tail) => any)
 ? Tail['length'] extends 0 ? O[K] : ExtractType<O[K], Tail> : never
}[T[0]]

// example Foo is number
type Foo = ExtractType<{ a: { b: { c: {d: number} } }, g: string }, ['a', 'b', 'c', 'd']> 

It is recursive type so depth is not restricted. Few things to consider:

  • ((...a: T) => any) extends ((a: any, ...args: infer Tail) => any) this part is used in order to cut the Head of the tuple, and work recursively with Tail. It means we traverse the object until tuple with keys will be empty. Every recursive call work with one element less.
  • Tail['length'] extends 0 ? O[K] : ExtractType<O[K], Tail> - we take the value type only when we are in the end of the key tuple

If you want to limit yourself to a depth of 2, so just a tuple as path, you can use the following type definition:

type ExtractType<
  O extends { [K1 in T[0]]: { [K2 in T[1]]: any } },
  T extends [string, string]
> = O[T[0]][T[1]];

type Foo = ExtractType<{ a: { b: number } }, ['a', 'b']> // number

Playground Link

Related