在接口的属性之间表达XOR的紧凑方法?

时间:2019-03-25 14:17:53

标签: typescript

与下面的代码相比,在接口的属性之间表达XOR的方法更紧凑吗?

interface IPositionedProps {
    zIndex?: number;
    sendToBack?: boolean;
    sendForward?: boolean;
}

interface IPositionedPropsWithSendToBack extends IPositionedProps {
    sendToBack?: boolean;
    sendToFront?: never;
    zIndex?: never;
}

interface IPositionedPropsWithSendToFront extends IPositionedProps {
    sendToBack?: never;
    sendToFront?: boolean;
    zIndex?: never;
}

interface IPositionedPropsWithZIndex extends IPositionedProps {
    sendToBack?: never;
    sendToFront?: never;
    zIndex?: number;
}

type PositionedProps =
    | IPositionedPropsWithSendToBack
    | IPositionedPropsWithSendToFront
    | IPositionedPropsWithZIndex;

1 个答案:

答案 0 :(得分:1)

如果目标是创建一个作为联合的类型,而该联合的每个成员都是单个属性,并且不允许指定该类型的任何其他属性,则应这样做:

type Id<T> = {} & { [P in keyof T]: T[P]}
type JustOneProp<T> = {
    [P in keyof T]-?: Pick<T, P> & Record<Exclude<keyof T, P>, never>
}[keyof T];


interface IPositionedProps {
    zIndex?: number;
    sendToBack?: boolean;
    sendForward?: boolean;
}
type PositionedProps = Id<JustOneProp<IPositionedProps>>

Id仅出于装饰性目的(将PickRecord弄平)可以删除。

类型JustOneProp接受T的每个属性,并创建一个类型,在该类型中,仅选择该属性(Pick<T, P>),而所有其他属性(Exclude<keyof T, P>)被{{ 1}}