首页 > 解决方案 > 在不同的类型检查(tsconfig)上创建编译器错误

问题描述

有人可以解释为什么这不会引发错误吗?

interface A {
    id?: number;
}
const a:A = {
    id: 5
};
const testA: boolean = (a === 1); //works, but why?


interface B {
    id: number;
}
const b:B = {
    id: 5
};
const testB: boolean = (b === 1); //compiler error -> expected that also on A

游乐场链接

标签: typescript

解决方案


让我们检查一下这种行为:

let foo: { foo?: number } = { foo: 1 };
foo = 1; // error, no common properties
foo === 1; // okay

在 TypeScript 2.4 及更高版本中,赋值失败是因为 的类型foo弱类型(所有属性都是可选的,比如Partial<Something>),没有与 . 相同的属性number。按照结构兼容性的正常规则(在 TS2.4 之前),这个赋值应该成功,因为只要 anumber没有任何名为foo的属性,就没有不兼容......在运行时(1).fooundefined,并且undefined是您期望的事情之一从. foo_ {foo?: number}但这是一个潜在的 bug 来源,因此 TS2.4 引入了弱类型检测来捕获它们;也就是说,使弱类型不兼容的语言阻止了可分配性。

然而,比较成功了,因为弱类型不兼容并没有阻止可比性。这两种类型仍然被认为具有可比性。为什么?好吧,我不确定动机是什么,但我可以看出它至少是故意的。有一次,有人推动更新正在成型的TypeScript 规范。我认为他们已经放弃了这样的更新(语言变化太快,他们没有足够的资源来不断地研究规范,结果是为了理解当前的语言,你需要继续阅读发行说明、GitHub 问题,甚至源代码),但我看到其中一个未合并的拉取请求microsoft/TypeScript#17215提供了有关可比性的详细信息。 具体来说

一个类型是否被认为是弱的与两个类型是否具有可比性无关

所以你去。可比性忽略了类型的弱点,因此您可以与 进行{foo?: number}比较number。这是故意的,尽管又一次,不知道为什么。

我猜你(或其他人)提交了microsoft/TypeScript#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有一个toFixed()返回string, 的方法(嗯,Number有它,并且在您访问它的成员时number被强制)该类型是重叠的弱类型。 Number{toFixed?(): string}number


好的,希望这有助于理解这种行为。祝你好运!

Playground 代码链接


推荐阅读