让我们检查一下这种行为:
let foo: { foo?: number } = { foo: 1 };
foo = 1; // error, no common properties
foo === 1; // okay
在 TypeScript 2.4 及更高版本中,赋值失败,因为foo
is a 弱型 http://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html#weak-type-detection(所有属性都是可选的,例如Partial<Something>
) 没有共同的属性number
。根据结构兼容性的正常规则(TS2.4 之前),此分配应succeed,因为只要一个number
没有any属性名为foo
,在运行时没有不兼容...(1).foo
is undefined
, and undefined
是你阅读时所期待的事情之一foo
from {foo?: number}
。但这是错误的潜在来源,因此 TS2.4 引入了弱类型检测来捕获它们;也就是说,语言使弱类型不兼容阻止可分配性.
然而,比较成功了,因为可比性弱类型不兼容性不会阻止。这两种类型仍然被认为具有可比性。为什么?好吧,我不确定动机是什么,但我可以看出它至少是故意的。有一段时间,有人推动更新模具TypeScript 规范 https://github.com/microsoft/TypeScript/blob/master/doc/spec.md。我认为他们已经放弃了这样的更新(语言变化太快,他们没有足够的资源来不断地研究规范,这样做的结果是,为了理解当前的语言,你需要继续阅读发行说明、GitHub 问题,甚至源代码),但我看到其中一个未合并的拉取请求,微软/TypeScript#17215 https://github.com/microsoft/TypeScript/pull/17215,提供了有关可比性的详细信息。具体来说 https://github.com/microsoft/TypeScript/pull/17215/commits/e2e20bd6f810dd210f641794ab6a46e0d98eb0a4#diff-a37bdfbd0d2f3627958003f87033871eR2396:
一个类型是否被认为是弱类型与两个类型是否具有可比性无关
那么就这样吧。可比性忽略了类型的弱点,因此您可以进行比较{foo?: number}
with number
。这是故意的,尽管再次不确定为什么。
我猜你(或其他人)提交了微软/TypeScript#36602 https://github.com/microsoft/TypeScript/issues/36602询问此事。如果我们想要改变这一点,这里要问的重要问题是:如果我们加强这一点,现实世界的 TypeScript 代码会破坏什么。如果数量很多,并且大多数损坏都没有捕获合法的错误,那么这种情况发生改变的可能性非常低。即使它只是在错误查找方面有所改进,它也可能会降低编译器性能太多,不值得。唯一确定的方法是 TS 团队同意考虑针对此更改的拉取请求。而且我并不在那个团队中所以????♂️。
最后,我们将之前的代码稍加修改进行对比,以确保我们理解非重叠弱类型、非重叠非弱类型和重叠弱类型之间的区别:
这是一个非重叠非弱类型:
let bar: { bar: number } = { bar: 1 };
bar = 1; // error, not assignable
bar === 1; // error, not comparable
赋值和比较都失败;这些类型在结构上不兼容。这是一个重叠的弱类型:
let baz: { toFixed?(): string } = { toFixed: () => "" };
baz = 1; // okay
baz === 1; // okay
赋值和比较均成功;自从number
has a toFixed()
方法返回一个string
, (出色地,Number
有它,并且number
被强迫Number
当您访问其成员时)类型{toFixed?(): string}
是一个弱类型,重叠number
.
好的,希望这有助于理解这种行为。祝你好运!
Playground 代码链接 https://www.typescriptlang.org/play/#code/DYUwLgBAZg9jBcEDe04H5EDsCuBbARiAE4QC+EAvMqghAIxkDcAULDJfYxAPTcTFEYRADQRM7AMYxcuGJggAHQQuJgAliADOrOJQpU6XXhBgBrAIYBPZs1CR85oohQOnYvIRLkqLx4gakLK4chjx8AkKi4pDmmppqAOaY5vigzMH6BkbhRIIiYjCQUrgKjimgEDZ2EA4AXs4QYDAAYmoAHiAAJmgAFACUiJpgRGqYCWQcKE2tHZ2I-ZQAfBAARCtM6ea1IdkmFtZ1ellhe1Y2QA