typescript 类型联合未检查多余属性[重复]

qncylg1j  于 2023-03-09  发布在  TypeScript
关注(0)|答案(2)|浏览(141)

此问题在此处已有答案

Typescript Discriminated Union allows invalid state(1个答案)
5天前关闭。
让我们假设a有一个具有属性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在向AB添加C属性时抱怨不一致的类型
怎样才能达到理想的类型?

szqfcxe2

szqfcxe21#

这是联合如何与多余的属性检查一起工作的一个小问题。除了多余的属性检查之外,{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

Playground链接
多余属性检查的怪癖在于,对于联合体,它允许来自 * any * 联合体成员的任何属性出现在赋值的对象字面量中。
如果并集构成要素彼此不兼容,则会出现错误:

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

Playground链接
如果联合有很多成员,也可以使用here中的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};

Playground链接

mnemlml8

mnemlml82#

我总是添加一些union的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' };

我们的目标是拥有一些共同的属性

相关问题