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"];
// }