Jih*_*ada 4 typescript mapped-types
假设我有一个对象:
\ntype Obj = { a: string, b: string, c: string }\nRun Code Online (Sandbox Code Playgroud)\n通过Partial<T>,TS 为您提供对象属性的所有可能组合,包括对象的完整形式。就我而言,我想排除完整的对象(如果可能的话,也排除空的对象)。
所以我想要:
\n{} // \xe2\x9d\x8c\n{ a: string } // \xe2\x9c\x85\n{ b: string } // \xe2\x9c\x85\n{ c: string } // \xe2\x9c\x85\n{ a: string, b: string } // \xe2\x9c\x85\n{ a: string, c: string } // \xe2\x9c\x85\n{ a: string, b: string, c: string } // \xe2\x9d\x8c\nRun Code Online (Sandbox Code Playgroud)\n我怎样才能做到这一点?
\n要实现此行为,您需要为该Obj类型创建两个约束。第一个应该排除“完整”类型,第二个应该排除“空”类型。
第一个约束意味着至少一个属性应该是类型的undefined(或者根本不存在)。因此,我们需要一个类型的联合,其中至少一个属性符合约束。
首先,我们必须映射初始类型以获取省略一个属性的所有可能的类型组合(注意修饰符?- 它确保允许可变数量的属性)并使用以下命令提取我们的并集keyof T:
{
[ P in keyof T ] : {
[ K in Exclude<keyof T, P> ] ?: T[P]
}
}[keyof T]
Run Code Online (Sandbox Code Playgroud)
如果我们保留它,我们仍然可以指定所有属性,因此我们需要明确告诉编译器不允许第三个属性。?修饰符确保我们可以省略该属性:
type NotAll<T> = {
[ P in keyof T ] : {
[ K in Exclude<keyof T, P> ] ?: T[P]
} & { [ M in P ] ?: never }
}[keyof T]
Run Code Online (Sandbox Code Playgroud)
第二个约束意味着至少应该定义一个属性。逻辑几乎是相同的,但是这次对于每个属性,我们都有一个所有属性的类型,除了一个设置为可选的与需要此属性的类型相交的属性:
type AtLeastOne<T> = {
[ P in keyof T ] : {
[ K in Exclude<keyof T, P> ] ?: T[P]
} & { [ M in P ] : T[M] }
}[keyof T];
Run Code Online (Sandbox Code Playgroud)
最后,我们需要将第二个约束与第一个约束结合起来。由于第一个约束为我们提供了允许类型的联合,AtLeastOne因此应该应用于联合的每个成员:
type NotAll<T> = {
[ P in keyof T ] : AtLeastOne<{
[ K in Exclude<keyof T, P> ] : T[P] //note the modifier is moved to `AtLeastOne`
}> & { [ M in P ] ?: never }
}[keyof T];
Run Code Online (Sandbox Code Playgroud)
就是这样,让我们测试一下我们的类型:
type test = NotAll<Obj>;
const empty : test = {}; //error
const a : test = { a: "test" }; //OK
const ab : test = { a: "test", b: "test" }; //OK
const bc : test = { b: "test", c: "test" }; //OK
const abc : test = { a: "test", b : "test", c: "test" }; //error
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1755 次 |
| 最近记录: |