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