类型联合不检查多余的属性

让我们想象一个具有属性AB或的对象C,例如:

const temp = {
  A: 1,
  B: 2,
}

或者

const temp = {
  C: 3,
}

直觉上,我认为这种类型为:

type T =  {A: number, B: number} | {C: number};

const valid: T = {A: 1, B: 2};
const alsoValid: T = {C: 3};

// Should complain but it does not
const invalid: T  = {A: 1, B: 2, C: 3};
// Also should complain
const alsoInvalid: T = {A:1, C: 3};

但是 TS 将此类类型视为{A?: number, B?: number, C?: number}并且基本上|使字段可选,但我希望 TS 在CA和添加属性时抱怨类型不一致B


如何存档所需的类型?

回答

这是工会如何与多余的财产检查结合工作的一个怪癖。除了多余的属性检查外,{A:1, C: 3}实际上与{C: number}以下兼容:

const o = {A:1, C: 3};
const ok: {C: number} = o; // No direct literal assignment, no excess property checks
const nok: {C: number} = { A:1, C: 3}; // Excess property checks kick in 

游乐场链接

多余的属性检查的怪癖是,对于联合,它允许来自任何联合成分的任何属性出现在分配的对象文字中。

如果联合组成部分与另一个组成部分不兼容,您可能会收到错误消息:

type T =  {A: number, B: number} | {C: number, A?: undefined, B?: undefined };

const valid: T = {A: 1, B: 2};
const alsoValid: T = {C: 3};

// Error
const invalid: T  = {A: 1, B: 2, C: 3};
//Error
const alsoInvalid: T = {A:1, C: 3};

游乐场链接

如果工会有很多成员,您也可以StrictUnion从这里使用


type UnionKeys<T> = T extends T ? keyof T : never;
type StrictUnionHelper<T, TAll> = T extends any ? T & Partial<Record<Exclude<UnionKeys<TAll>, keyof T>, never>> : never;
type StrictUnion<T> = StrictUnionHelper<T, T>

type T =  StrictUnion<{A: number, B: number} | {C: number }>;

const valid: T = {A: 1, B: 2};
const alsoValid: T = {C: 3};

// Error
const invalid: T  = {A: 1, B: 2, C: 3};
//Error
const alsoInvalid: T = {A:1, C: 3};

游乐场链接


以上是类型联合不检查多余的属性的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>