【问题标题】:Typescript interface with BOTH properties or NEITHER具有两个属性或都没有的 Typescript 接口
【发布时间】:2019-04-03 01:02:28
【问题描述】:

我有“成对出现”的键值对。换句话说,如果我有一个键值对A:B,那么我还想要求我的对象有C:D,但它也可以没有一对。 (想想message:string 是一对,min-length:number 是另一对。)有没有一种优雅的方法来制作由任意数量的此类对组成的接口?

编辑: 为了澄清起见,我想为允许这些对象设计一个接口:

{
    //First pair
    message1: string;
    minLength1: number;
    //Second pair
    message2: string;
    minLength2: number;
    // ...
}

{
    //First pair omitted altogether

    //Just the second pair
    message2: string;
    minLength2: number;
}

...但是像下面这样的对象是不允许的,因为你只有一对的一半:

{
    //First pair
    message1: string;
    // minLength1: number; // Error †
    // ...
}

† 错误:如果包含message1,那么您还必须包含minLength1

【问题讨论】:

    标签: typescript interface


    【解决方案1】:

    对于给定的一对属性,您可以做出的最接近要求两个属性或都不要求的最接近的近似值是具有两个属性的类型和具有never 类型的可选属性的类型的联合(这会阻止属性出现undefined 以外的值)。我从this answer 得到了这个想法。这将在正确的情况下给您一个错误,尽管错误消息可能不是特别有用。然后你可以为你想要的所有属性对相交并集(只要你没有超过 10 对,因为当 TypeScript 简化一个类型时,它会分配并集的交集来生成交集的并集,这将以指数方式放大类型的大小)。以您为例:

    type AllOrNone<T> = T | {[K in keyof T]?: never};
    
    type MyType = AllOrNone<{
        message1: string;
        minLength1: number;
    }> & AllOrNone<{
        message2: string;
        minLength2: number;
    }>;
    

    如果您真的对undefined 案例感到困扰并愿意使用通用函数来验证您的对象而不是写下单一类型,那么您可以执行以下操作:

    type CheckAllOrNone<A, T> =
        T | (keyof A & keyof T extends never ? {} : never);
    
    type CheckMyType<A> = CheckAllOrNone<A, {
        message1: string;
        minLength1: number;
    }> & CheckAllOrNone<A, {
        message2: string;
        minLength2: number;
    }>;
    
    function checkMyType<A extends CheckMyType<A>>(arg: A) {
        return arg;
    }
    

    【讨论】:

    • 太棒了——非常感谢!
    猜你喜欢
    • 2021-09-26
    • 2020-11-14
    • 2019-10-24
    • 1970-01-01
    • 2016-07-18
    • 1970-01-01
    • 2019-09-30
    • 2014-11-28
    • 1970-01-01
    相关资源
    最近更新 更多