I have an object of this type
interface Obj {
key1: SubType1;
key2: SubType2;
}
Where SubType1 and SubType2 are all given.
type Name = "LOL" | "HAHA";
type Statu = "Active" | "Inactive";
interface SubType1 {
key: {
name: Name;
};
}
interface SubType2 {
status: Statu;
}
I implemented a function which takes the object and other object called transformObject as its argument. The transform object has a recursive generic type so it knows the structure of the object provided. The point of this function is to conveniently traverse the object with transformObject and change a specific field of that object while conforming to the original type.
Here is the imlementaion
type MappedTransform<T> = {
[K in keyof T]?: MappedTransform<T[K]> | ((params: T[K]) => T[K]);
};
function foo<T>(obj: T, transformObject: MappedTransform<T>) {
// I omit the implementaion details for this function to make the question simple
}
foo(obj, {
key1: {
key: {
name: "HAHA" // here the value that `name` field can change to can only be
// either `HAHA` or `LOL` because `MappedTransform` enforces that it has to be of the original type
}
}
});
My question is, if I want to use another type to lock where transformObject can reach, in other words, ideally if I do this
foo<Obj, Name>(obj, transformObject);
the transformObject can only be at the level of Name type, not on any other types e.g. Status.
so this should give me error because status is not of type Name, its type is Status
foo<Obj, Name>(obj, {
key2: {
status: 'Inactive' // this should give me error since it is not of the type `Name` provided in the generic
}
});
https://codesandbox.io/s/ts-recursive-function-tmo11?file=/src/index.ts
This is a live demo you can play with