I have a recursive function that takes an object with a generic interface. The function traverses the object and creates a new object with almost exactly the same interface, except for the end-nodes/leafs, it transforms them into numbers. The function returns this new object, but I cannot find out how to give this the correct type.
Example:
interface IOriginal
{
prop1: string,
prop2: number,
prop3: {
prop1: boolean,
prop2: {
prop1: number
},
prop3: string
}
}
const input : IOriginal = {
prop1: "somestring",
prop2: 5,
prop3: {
prop1: true,
prop2: {
prop1: 2
},
prop3: "otherstring"
}
}
function traverse<T>(obj: T)
{
/* ... map the object ... */
return mappedObj
}
const output = traverse(input)
and output's (mapped object's) interface should look like
interface IOutput
{
prop1: number,
prop2: number,
prop3: {
prop1: number,
prop2: {
prop1: number
},
prop3: number
}
}
With mapped types I can only seem to map the first level of depth, if that makes sense.
You can use conditional types to achieve this result:
type LeafsToNumbers<T> =
T extends string | number | boolean ? number : // If primitive transform to number
{ [ P in keyof T] : T[P] extends (infer U)[] ? LeafsToNumbers<U>[] : LeafsToNumbers<T[P]> }; // Otherwise recursively map, with a special case for arrays.
function traverse<T>(obj: T) : LeafsToNumbers<T>
{
/* ... map the object ... */
return null as any;
}
let a: IOriginal;
let o = traverse(a);
o.prop1 //number
o.prop3.prop1 // number
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With