为啥 Typescript 允许将 `a: 1, b: 2` 分配给类型 `a: any | b:任何`? [复制]

Posted

技术标签:

【中文标题】为啥 Typescript 允许将 `a: 1, b: 2` 分配给类型 `a: any | b:任何`? [复制]【英文标题】:Why does Typescript allow `a: 1, b: 2` to be assigned to type `a: any | b: any`? [duplicate]为什么 Typescript 允许将 `a: 1, b: 2` 分配给类型 `a: any | b:任何`? [复制] 【发布时间】:2020-04-15 03:43:50 【问题描述】:

考虑这段代码:

let foo: a: any | b: any = a: 1, b: 2;

我希望 TypeScript 拒绝此代码,因为此联合类型表示第一种类型或第二种类型,并且该值不能分配给它们中的任何一个,因此类型检查应该拒绝它。但实际上它通过了,为什么呢?

(对于背景,上述类型旨在成为“此属性或该属性,但不是两者,类型”。请参阅Typescript Interface - Possible to make "one or the other" properties required?)

【问题讨论】:

【参考方案1】:

根据the blog post introducing union excess property checking in TypeScript 3.5,TypeScript 会检查它是否属于至少一种类型

在 TypeScript 3.4 及更早的版本中,某些多余的属性被允许在不应该出现的情况下使用。例如,TypeScript 3.4 允许在对象字面量中使用不正确的 name 属性,即使它的类型在 Point 和 Label 之间不匹配。

type Point = 
    x: number;
    y: number;
;

type Label = 
    name: string;
;

const thing: Point | Label = 
    x: 0,
    y: 0,
    name: true // uh-oh!
;

以前,非区分联合不会对其成员进行任何多余的属性检查,因此,错误类型的名称属性会溜走。

在 TypeScript 3.5 中,类型检查器至少会验证所有提供的属性是否属于某个联合成员并具有适当的类型,这意味着上面的示例正确地发出了错误。

博文继续明确描述重叠是有效的:

请注意,只要属性类型有效,仍然允许部分重叠。

const pl: Point | Label = 
    x: 0,
    y: 0,
    name: "origin" // okay
;

基于短语“所有提供的属性都属于某个联合成员并具有适当的类型”,似乎多余的属性检查器无法将这些属性视为互斥的。

【讨论】:

您可能想稍微扩展您的报价,因为下一部分明确表示问题中的代码之类的内容仍然可以。 (但没有说明原因。) @user2357112supportsMonica 很公平,这部分确实明确地解决了这种情况(即使它似乎没有添加任何其他有助于推理或内部的东西)。已编辑。

以上是关于为啥 Typescript 允许将 `a: 1, b: 2` 分配给类型 `a: any | b:任何`? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 TypeScript 中的类允许使用鸭子类型

为啥我的 Typescript 对象允许这个额外的属性?

为啥允许使用 kebab-case 非标准属性,而不允许使用其他属性?以及如何在 TypeScript 中定义这样的类型?

为啥我不能访问 TypeScript 私有成员?

为啥在另一个 Typescript 项目中导入时没有得到导出的对象?

为啥 tslint 中不允许按位运算符?