如何在带有Omit <>的Typescript中使用“或”运算符?

时间:2019-09-16 08:30:47

标签: typescript typescript-typings

此代码:

type WithOr = {a:string} & ({b?:true, c?:never} | {b?:false, c:number})
type Ommited = Omit<WithOr, 'a'>
const m1: Ommited = {b: true};
const m2: WithOr = {...m1, a: 'a'}

最终将出现错误:

...
Type 'boolean | undefined' is not assignable to type 'false | undefined'.
...

似乎Omit抛弃了“或”逻辑。

还有其他方法可以使用Omit(在其中带有“或”符号)重用我的复杂类型吗?

这里是running playground

1 个答案:

答案 0 :(得分:1)

这与Omit的工作方式有关。在lib.es5.d.ts中定义的方式如下:

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;

Exclude<keyof T, K>生成所有键的并集,除了您作为K传递的键之外。因此,在您的示例中为'b' | 'c'

Pick然后使用映射类型迭代这些键并创建新的对象类型:

type Pick<T, K extends keyof T> = {
    [P in K]: T[P];
};

因此,该类型被“展平”。对于bT['b']返回true | false | undefined,TypeScript将其简化为boolean | undefined

结果是:

type Ommited = {
    b?: boolean | undefined;
    c?: number | undefined;
}

我认为您在这里可以做的最好的事情是将“或”部分提取到命名类型中,然后重复使用:

type OrPart = {b?:true, c?:never} | {b?:false, c:number}
type WithOr = {a:string} & OrPart
const m1: OrPart = {b: true};
const m2: WithOr = {...m1, a: 'a'}

Playground