我已经使用下面的守卫打字null
object prop,但仍然出现错误:
function a(par: {a: string; b: null | string}): {a: string; b: string} | undefined {
if (par.b === null) {
return;
}
return par;
}
输入 '{ a: 字符串; b:字符串|无效的; }' 不可分配给类型 '{
a:字符串; b:字符串; }'。属性“b”的类型不兼容。
输入“字符串|” null' 不可分配给类型'string'。
类型“null”不可分配给类型“string”。
我想如果我防守检查par.b === null
,TS 应该推断不可能返回具有以下内容的对象:prop.b === null
.
或者我在这里混淆了一些东西?
TL;DR:您并不疯狂,但您对编译器的期望超出了它所能提供的范围。使用类型断言并继续。
TypeScript 并不倾向于确定类型保护检查的所有可能含义。检查对象的属性可以缩小对象本身类型的少数几个地方之一是当对象是受歧视联盟并且您正在检查的属性是判别性属性。就你而言,par
本身甚至不是一个工会类型,更不用说是一个受歧视的工会了。所以当你检查时par.b
编译器确实缩小了范围par.b
但不会将这种向上缩小的范围传播为par
本身。
It could这样做,但问题是这种计算对于编译器来说很容易变得昂贵,如中所述一位语言架构师的评论:
似乎对于每一个参考x
在控制流图中,我们现在必须检查每个类型保护x
作为点名称中的基本名称。换句话说,为了知道类型x
我们必须查看所有类型保护的属性x
。这有可能产生大量工作。
如果编译器像人类一样聪明,它可能只在这些额外检查可能有用时才执行它们。或者聪明的人可以写出一些对于这个用例来说足够好的启发式方法;但我想实际上这并不是任何人进入该语言的优先考虑事项。我还没有找到GitHub 中的开放问题这表明了这一点,所以如果您对此有强烈的感觉,您可能想要提交一份文件。但不知道反响如何。
在没有更聪明的编译器的情况下,有一些解决方法:
最简单的解决方法是接受你比编译器更聪明的事实并使用类型断言告诉它你确信你所做的事情是安全的,并且它不应该太担心验证它。一般来说,类型断言有点危险,因为如果您使用类型断言并且断言是错误的,那么您只是对编译器撒了谎,由此产生的任何运行时问题都是您的错。但在这种情况下,我们可以非常有信心:
function aAssert(par: {
a: string;
b: null | string;
}): { a: string; b: string } | undefined {
if (par.b === null) {
return;
}
return par as { a: string; b: string }; // I'm smarter than the compiler
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)