首页 > 解决方案 > 类型联合不检查多余的属性

问题描述

让我们假设一个对象具有属性ABC,例如:

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 在我添加属性时|抱怨类型不一致CAB


如何归档所需的类型?

标签: typescript

解决方案


这是工会如何与过多的财产检查相结合的一个怪癖。除了多余的属性检查之外,{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};

游乐场链接

如果工会有很多成员,您也可以使用StrictUnionfrom here


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};

游乐场链接


推荐阅读