具有两个属性或NEITHER

时间:2018-10-30 02:43:50

标签: typescript interface

我有“成对出现”的键值对。换句话说,如果我有一个键值对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

1 个答案:

答案 0 :(得分: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;
}