Home > Blockchain >  Typescript: How to convert an object type to paths mapper?
Typescript: How to convert an object type to paths mapper?

Time:08-26

I want to generate a paths mapper type from an object type, just like below.

type NestedObject = {
  prop1: {
    prop1_1: string;
  };
  prop2: string;
  prop3: {prop3_1: string;}[];
}

// convert to
type PathsMapFromNestedObject = {
  prop1: ["prop1"];
  prop1_1: ["prop1", "prop1_1"];
  prop2: ["prop2"];
  prop3: ["prop3"];
  prop3_1: ["prop3", number, "prop3_1"]
}

CodePudding user response:

You could do it like this:

type Paths_<T, P extends (string | number)[] = []> = {
  [K in keyof T]: [...P, K] | (T[K] extends any[] 
    ? Paths_<T[K][number],  [...P, K & string, number]>
    : T[K] extends object 
      ? Paths_<T[K], [...P, K & string]>
      : never
  )
}[keyof T]

type Paths<T> = { 
  [
    K in Paths_<T> extends infer U 
      ? U 
      : never 
    as K extends [...any, infer L extends string] 
      ? L 
      : never
  ]: K 
}

Paths_ is a recursive type which traverses through the object. It builds a union with a tuple of string | number for each property inside the object. The generic type P is used to store the current path as a tuple.

Paths calls the recursive type and builds an object from the union using a mapped type.


And here is the result.

type PathsMapFromNestedObject = Paths<NestedObject>
// type PathsMapFromNestedObject = {
//     prop1: ["prop1"];
//     prop1_1: ["prop1", "prop1_1"];
//     prop2: ["prop2"];
//     prop3: ["prop3"];
//     prop3_1: ["prop3", number, "prop3_1"];
// }

Playground

  • Related