TypeScript中if守卫无法收窄内联闭包变量类型求助
TypeScript闭包中类型收窄失效问题解惑
先看你给出的代码:
function printSomeValue(someValue: string) { console.log(`${someValue}`) } function doSomething(closure: () => void) { closure() } let str: string | undefined str = 'It should work' if (str) { doSomething(() => printSomeValue(str)) }
这段代码里,明明已经通过if (str)做了类型收窄,确认str是string,但闭包里的str还是被识别为string | undefined,导致报错。
原因分析
TypeScript的类型收窄只在当前作用域内有效。闭包是延迟执行的,它捕获的是变量str的引用,而不是当前作用域里str的具体值。编译器无法保证在闭包执行时,str的值没有被修改——比如在if块之后,你完全可以把str重新赋值为undefined,这时候闭包执行就会出问题。所以编译器不会把闭包里的str类型收窄为string。
解决方案
这里有几种实用的解决方法:
用块级常量保存收窄后的值:
在if块里把str赋值给一个常量,常量的类型会被自动收窄为string,闭包捕获这个常量就不会有类型问题:if (str) { const strCopy = str; doSomething(() => printSomeValue(strCopy)) }使用非空断言(谨慎使用):
如果你能确保闭包执行时str一定是string,可以用!断言它不为undefined:if (str) { doSomething(() => printSomeValue(str!)) }注意:非空断言会跳过TypeScript的类型检查,要是后续代码里
str被意外修改为undefined,运行时会报错,所以只在你能完全控制变量生命周期时用。
内容的提问来源于stack exchange,提问作者code_mechanic
相关产品推荐
相关产品推荐

