我想递归地映射一个对象,以便将对象中的原始值转换为其他类型。
例如,我想要一个这样的对象:
const before = { a: { c: '' }, b: [ '', { d: '' } ] }
Run Code Online (Sandbox Code Playgroud)
变成这样:
const after = { a: { c: Test }, b: [ Test, { d: Test } ] }
Run Code Online (Sandbox Code Playgroud)
我还假设值会不会Date,Symbol或空/空。只是 JSON 可序列化类型,如字符串、数字等(空值除外)
这是我尝试过的:
type ConvertToTest<T> = {
[P in keyof T]: T[P] extends any[]
? ConvertToTest<T[P]>
: T[P] extends {}
? ConvertToTest<T[P]>
: Test;
}
function convert<T>(o: T): ConvertToTest<T> {
// ...
}
Run Code Online (Sandbox Code Playgroud)
这是使用Typescript 2.8 中引入的条件类型。
const after = convert(before)结果在编辑器中after.a.c使用string类型补全 for c,而不是补全 for Test。
如何重写type ConvertToTest<T>以说服after.a.c类型为 的Typescript Test?
编辑:这是说明上述内容的Typescript Playground 链接。
所以你需要从ConvertToTest<T>类型中获得两件事。一个是 ifT是原始类型,则CovertToTest<T> = Test. 另一个是如果T不是原始的,您希望保留相同的键但转换它们的值。
为此,我只需将第一个 case 添加为条件类型的一部分,然后让另一个分支使用递归映射类型:
type Primitive = string | number | boolean | null | undefined;
type ConvertToTest<T> = T extends Primitive ? Test : {
[K in keyof T]:
T[K] extends (infer U)[] ? ConvertToTest<U>[] :
ConvertToTest<T[K]>;
}
Run Code Online (Sandbox Code Playgroud)
使用它,您可以像这样使用它:
// For example. Replace with whatever your actual type is.
type test = {
foo(): string;
}
declare function convertToTest<T>(obj: T): ConvertToTest<T>;
const test = convertToTest({ a: "", b: { c: true, primArr: [1, ""], objArr: [{inner: ""}] } });
test.a.foo(); // OK
test.b.c.foo(); // OK
test.b.primArr[0].foo() // OK
test.b.objArr[0].inner.foo() // OK
Run Code Online (Sandbox Code Playgroud)
这是一个很好的方法,因为它适用于任何深度的对象,并且也将正确处理转换数组类型的元素。
| 归档时间: |
|
| 查看次数: |
1118 次 |
| 最近记录: |