假设您有一个类似
的界面interface Foo {
a?: number[];
b?: number[];
c?: number[];
d?: number[];
}
是否可以声明一个可以接受两个属性(例如a
和b
或a
和c
的任意组合但拒绝三个属性的类型(例如a
,b
,c
)?
I've made a TypeScript Playground可以说明我的期望。
type Bar =
{ a: number[]; b: number[]; } |
{ a: number[]; c: number[]; } |
{ a: number[]; d: number[]; };
function foo(a: Bar): void {
console.log(a);
}
foo({ a: [1, 2], d: [1, 2] });
foo({ a: [1, 2], b: [1, 2], d: [1, 2] }); // Expected failure
答案 0 :(得分:3)
您可以使用两种条件类型对键进行两次迭代,并获得两个键的所有可能组合的并集。不幸的是,该解决方案不能扩展到任意数量的键(类型别名不能轻易地递归),但是您可以为特定数量的组合创建相似的类型。
interface Foo {
a?: number[];
b?: number[];
c?: number[];
d?: number[];
}
type RequireTwoHelper<T, K1 extends keyof T, K2 extends keyof T> =
K2 extends string ? { [P in K1 | K2]-?:T[P] } : never;
type RequireTwo<T, K1 extends keyof T> =
K1 extends string ? RequireTwoHelper<T, K1, Exclude<keyof T, K1>> : never;
type RequireTwoFoo = RequireTwo<Foo, keyof Foo>
let foo: RequireTwoFoo= { a:[], b:[] };
let foo2: RequireTwoFoo= { a:[], c:[] }
let foo3: RequireTwoFoo = { a: [], d: [] }
let foo4: RequireTwoFoo = { b: [], c: [] }
let foo5: RequireTwoFoo = { b: [], d: [] }
let foo6: RequireTwoFoo = { c: [], d: [] }
let foo7: RequireTwoFoo = { a[], c: [], d: [] } //err