【问题标题】:Require Two of Four Properties需要四个属性中的两个
【发布时间】:2019-02-05 16:30:05
【问题描述】:

假设你有一个类似的界面

interface Foo {
    a?: number[];
    b?: number[];
    c?: number[];
    d?: number[];
}

是否可以声明一个类型,它可以接受两个属性的任意组合(例如,abac)但会拒绝三个属性(例如,a、@ 987654328@,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

【问题讨论】:

    标签: typescript typescript3.0


    【解决方案1】:

    您可以使用两种条件类型对键进行两次迭代,并获得两个键的所有可能组合的并集。不幸的是,该解决方案不能扩展到任意数量的键(类型别名不容易递归),但您可以为特定数量的组合创建类似的类型。

    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
    

    Playground link

    【讨论】:

      猜你喜欢
      • 2015-10-28
      • 2012-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-10
      • 2012-03-01
      • 1970-01-01
      • 2012-06-06
      相关资源
      最近更新 更多