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

qwe*_*rty 6 typescript

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

const temp = {
  A: 1,
  B: 2,
}
Run Code Online (Sandbox Code Playgroud)

或者

const temp = {
  C: 3,
}
Run Code Online (Sandbox Code Playgroud)

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

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};
Run Code Online (Sandbox Code Playgroud)

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


如何存档所需的类型?

Tit*_*mir 8

这是工会如何与多余的财产检查结合工作的一个怪癖。除了多余的属性检查外,{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 
Run Code Online (Sandbox Code Playgroud)

游乐场链接

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

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

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};
Run Code Online (Sandbox Code Playgroud)

游乐场链接

如果工会有很多成员,您也可以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};
Run Code Online (Sandbox Code Playgroud)

游乐场链接

  • 我相信你的解决方案更优雅 (3认同)

cap*_*ian 5

我只是总是添加一些type工会。例如:

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


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

// Should complain but it does not
const invalid: T = { A: 1, B: 2, C: 3, type: "ONE" };
// Also should complain
const alsoInvalid: T = { A: 1, C: 3, type: 'TWO' };
Run Code Online (Sandbox Code Playgroud)

目标是拥有一些共同财产

  • 建立一个受歧视的工会绝对也是一个有效的想法 (2认同)