为什么 Typescript 允许将 `{a: 1, b: 2}` 分配给类型 `{a: any} | {b:任何}`?

gol*_*pot 6 typescript

考虑这个代码:

let foo: {a: any} | {b: any} = {a: 1, b: 2};
Run Code Online (Sandbox Code Playgroud)

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

(对于背景,上述类型旨在成为“此属性或该属性,但不是两者都类型”。请参阅Typescript 接口 - 是否需要“一个或另一个”属性?

Jef*_*ica 5

根据在 TypeScript 3.5 中介绍联合多余属性检查的博客文章,TypeScript 将检查它是否属于至少一种类型

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

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

type Label = {
    name: string;
};

const thing: Point | Label = {
    x: 0,
    y: 0,
    name: true // uh-oh!
};
Run Code Online (Sandbox Code Playgroud)

以前,非歧视联合不会对其成员进行任何多余的属性检查,因此,错误键入的 name 属性被忽略了。

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

博文继续明确地将重叠描述为有效:

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

const pl: Point | Label = {
    x: 0,
    y: 0,
    name: "origin" // okay
};
Run Code Online (Sandbox Code Playgroud)

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