let a = [];
a.push(0);
Run Code Online (Sandbox Code Playgroud)
上面的代码编译得很好
noImplicitAny
都strictNullChecks
设置为 truenoImplicitAny
都strictNullChecks
设置为 false但它会在第二行发出错误
noImplicitAny
是假的,strictNullChecks
也是真的发出的错误是Argument of type 'number' is not assignable to parameter of type 'never'.
似乎在前两种情况下a
被推断为 a any[]
,而在最后一种情况下它被推断为 a never[]
,但为什么会发生这种情况呢?如果noImplicitAny
是假的,难道它不应该仍然能够推断出它是吗any[]
?any[]
相反,为什么要像第一种情况那样推断出哪里noImplicitAny
是真的?似乎预期的行为以某种方式逆转了......
检查下面所附的图像,了解所使用的错误和选项。
jca*_*alz 26
此问题是在microsoft/TypeScript#36987中提出的。权威的(但不是特别丰富的)答案是这种行为是预期的,并且是向后兼容性所必需的。一般来说,TypeScript 不会引入重大更改,除非这些更改改进的东西比它们破坏的东西多得多。
当编译--noImplicitAny
器选项和编译--strictNullChecks
器选项都启用时,空数组并不是真正的类型any[]
;相反,它们是“自动”或“通配符”或“进化”类型,这些类型根据观察到要添加到其中的值而变化。这是在microsoft/TypeScript#11432中实现的:
let a = []; // auto-typed
a.push(0); // now a is seen as number[]
a.map(x => x.toFixed()) // okay
a.map(x => x.toUpperCase()) // error, numbers don't have a toUpperCase() method
Run Code Online (Sandbox Code Playgroud)
当--noImplicitAny
关闭时,这种情况不会发生,因为这样做会给以前“很好”的现有代码添加新的错误(如果是a
类型any[]
,那么x
在map()
方法中应该是类型any
,所以在x.toUpperCase()
或打字错误之类的x.toFaxed()
)。
至于--strictNullChecks
打开或关闭之间的区别,修复了几个与空数组文字与其他用例交互不良有关的错误;请参阅microsoft/TypeScript#19576和microsoft/TypeScript#19745。这些修复更改了打开时的行为--strictNullChecks
,但没有更改关闭时的行为,同样是为了在其他用例中保持向后兼容性。
这或多或少就是正在发生的事情。您会看到多个功能和错误修复在某些编译器选项面前以特殊方式相互作用的后果。
务实地说,您应该尽可能使用全套--strict
编译器选项。这为您提供了“标准”量的类型安全性,并且被广泛使用,因此社区中有大量的文档和讨论。如果您有选择地禁用某些编译器选项,并且遇到奇怪或意外的情况,那么您可用的资源就会减少,因为您可能是拥有此类配置的极少数人之一。即使你发现了真正的语言错误,修复它的压力也会较小,因此它可能会持续很长一段时间或永远。
归档时间: |
|
查看次数: |
1474 次 |
最近记录: |