'Replace a specific type with another type in a nested object typescript
I want to replace a specific type with another type, as so:
interface Human {
name: string;
age: number;
isMarried: boolean;
animals: [
{ name: string, age: number},
{ name: string, age: number}
]
}
type HumanString = ReplaceTypes<Human, number, string>
/*
HumanString {
name: string;
age: string;
isMarried: boolean;
animals: [
{ name: string, age: string},
{ name: string, age: string}
]
}
*/
Where the has the following interface ReplaceTypes<OriginalType, OldType, NewType>
Oldtype should be replaced in all nested occurances for NewType
Solution 1:[1]
You can do that with a recursive mapped type that looks like this:
type ReplaceTypes<ObjType extends object, FromType, ToType> = {
[KeyType in keyof ObjType]: ObjType[KeyType] extends object
? ReplaceTypes<ObjType[KeyType], FromType, ToType> // Recurse
: ObjType[KeyType] extends FromType // Not recursing, need to change?
? ToType // Yes, change it
: ObjType[KeyType]; // No, keep original
}
So for instance, if you had example: HumanString, example.age and example.animals[number].age would both be string instead of number.
It looks to see if the type of each property extends object and if so, recurses; otherwise, it looks to see if the type extends the "from" type and replaces it if so.
All of those repeated instances of ObjType[KeyType] get tiresome, so you could split it up into two parts:
type ReplaceType<Type, FromType, ToType> =
Type extends object
? ReplaceTypes<Type, FromType, ToType>
: Type extends FromType
? ToType
: Type;
type ReplaceTypes<ObjType extends object, FromType, ToType> = {
[KeyType in keyof ObjType]: ReplaceType<ObjType[KeyType], FromType, ToType>;
}
If you wanted to be able to do this with FromType being an object, type, it should work if you change the order:
type ReplaceType<Type, FromType, ToType> =
Type extends FromType // FromType?
? ToType // Yes, replace it
: Type extends object // Recurse?
? ReplaceTypes<Type, FromType, ToType> // Yes
: Type; // No, leave it alone
type ReplaceTypes<ObjType extends object, FromType, ToType> = {
[KeyType in keyof ObjType]: ReplaceType<ObjType[KeyType], FromType, ToType>;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
