这样的代码可以通过类型检查吗?
function infiniteLoop(): never {
while (true) {
}
}
let x = infiniteLoop();
x
如何存在并因此居住在never
类型中?
答案 0 :(得分:2)
never
是一种类型。任何变量都可以具有这种类型(因为任何变量都可以具有任何类型)。因此,当您说let x = infiniteLoop()
时,Typescript推断x
的类型为never
。很好。
但是,这就是有用的地方,它阻止您稍后使用x
。那才是真正的语义错误。
有关更多示例,请参见this explanation。
更一般地说,您不能从类型系统中期望它会静态处理无限循环检测。这是因为它是类型系统的undecidable problem。
当您显式提供never
类型提示时,Typescript方法可以静态地查明不需要的行为。具体来说,它可以防止您使用显式声明为无止境的计算结果(或从声明为无止境的计算返回)。
答案 1 :(得分:1)
我将尝试回答自己的问题。 never
seems to be "bottom" type。但是“底部”是任何其他类型的子类型:
function f() : never
{
return (1 as never); // but is not true for "as void".
}
底部是各种类型的居民(尽管有一些警告) 关于未装箱种类的类型),无论何时何处都可以使用底部 该类型的值将为(here)。
因此,infiniteLoop()
可以返回never
,任何类型都包含never
作为其子类型,甚至可以声明它:
let x:never;
并且由于它是任何其他类型的子类型,因此可以将它们的值“广播”(使用as
)到never
。但是无法将超集分配给它的子集,例如将Triangle
类型设置为never
-这就是我们在这里得到错误的原因:
type Shape = Square | Rectangle | Circle | Triangle;
function assertNever(x: never): never {
throw new Error("Unexpected object: " + x);
}
function area(s: Shape) {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.height * s.width;
case "circle": return Math.PI * s.radius ** 2;
default: return assertNever(s); // error here if there are missing cases
}
}
答案 2 :(得分:0)
我认为因为类型确定。如果您想查看消息this code will not be never reach because of infinity loop
的类型,可以安装声纳皮棉,它应该显示错误