我需要递归地遍历数据结构并创建一个 type
,根据条件将某些字段更改为不同的类型。
基于以下结构,我需要创建一个类型 (Result
),其中所有 A
类型都替换为 B
类型。
class A{}
class B{}
const data = {
propA:new AA,
propB:true,
nested:{
propC:new AA,
propD:false
}
}
// something like:
type Replace<typeof data, A, B>
// result
type Result = {
propA:B,
propB:boolean,
nested:{
propC:B
propD:boolean
}
}
答案 0 :(得分:2)
您可以使用映射类型执行此操作,但请记住,匹配基于对象结构而不是类名称,因此当您定位 class C{}
时,A
中的对象也将被转换}}。
Replace
类型可以定义为
type Replace<T, From, To> = T extends (...args: any[]) => any ? T : {
[K in keyof T]:
[T[K], From] extends [From, T[K]] ? To : Replace<T[K], From, To>
}
第一个条件是保留任何方法/函数属性,因为映射类型会将它们转换为 {}
。映射类型本身处理每个键,并检查值是否扩展了 From
类型和 From
类型扩展了值类型,以确保相等。如果两者相等,则用 To
替换该值,否则以递归方式调用 Replace
。
以下是转换示例:
class A{}
class B{b = 42}
class C{}
const data = {
propA: new A(),
propBool: true,
propC: new C(),
nested:{
propA: new A(),
propBool: false
},
f: () => 42
}
type Result = Replace<typeof data, A, B>
// type Result = {
// propA: B;
// propBool: boolean;
// propC: B;
// nested: {
// propA: B;
// propBool: boolean;
// };
// f: () => number;
// }
答案 1 :(得分:1)
这可以通过条件递归类型来实现:
class A {
ClassPropA!: string
}
class B {
ClassPropB!: string
}
const data = {
propA: new A(),
propB: true,
nested:{
propC: new A(),
propD:false
}
}
type Replace<T, A, B> = T extends object
? { [key in keyof T]: T[key] extends A ? B : Replace<T[key], A, B> }
: T;
// type Result = {
// propA: B,
// propB: boolean,
// nested:{
// propC: B
// propD: boolean
// }
//
// }
type Result = Replace<typeof data, A, B>;