为什么 TS 不警告 'typeof' 和"in"的不可能条件?



在4.9的公告中,他们已经用'In'描述了更好的缩小范围。因此,我把他们的例子带到操场上进行了修改。我发现typeofin的不可能条件被缩小到never,而不是生成警告或错误:

// Should be illegal but doesn't error out...?
if (typeof packageJSON.name === "string" && typeof packageJSON.name === "number") {

我认为TypeScript能够推断出packageJSON.name是一个字符串,这意味着检查packageJSON.name的类型是否是右边的数字应该是不可能的。令我沮丧的是,我还发现检查文字并不能让TypeScript抱怨:

typeof 123 === "string" // OK, but is obviously impossible?

in:也表现出这种行为

// How can it both have and not have the "name" key?
if (packageJSON && typeof packageJSON === "object" && "name" in packageJSON && !("name" in packageJSON)) {

为了澄清,类型被正确地缩小为到never,但我的期望是TypeScript应该能够警告我使用不可能的条件。TypeScript已经为相等性检查执行了此操作:

// TS knows that packageJSON is 0, so the RHS is impossible
if (packageJSON === 0 && packageJSON === 1) {

我不知道为什么会发生这种事。它是设计的还是限制的?我能做些什么来防止或警告这种情况(可能是门楣(?这里有一个操场,上面有几个例子。

TypeScript能够在根据条件确定类型不可能的情况下缩小类型。在第一个例子中,由于TypeScript知道packageJSON.name是一个字符串,它可以推断右边的条件是不可能的,并将类型缩小为never。在第二个例子中,TypeScript知道文字123是一个数字,因此它可以推断右侧的条件是不可能的,并将类型缩小为never。在第三个例子中,TypeScript知道packageJSON是一个对象;name";key存在于packageJSON上,因此它可以推断右侧的条件是不可能的,并将类型缩小为never。

这种行为是经过设计的,因为TypeScript在某些情况下能够缩小类型。但是,如果要防止这种行为,可以使用类似TSLint的linter。

最新更新