typescript 如果guard没有缩小内联闭包值,则键入脚本

hujrc8aj  于 2022-11-18  发布在  TypeScript
关注(0)|答案(1)|浏览(140)

可能有人帮助我理解,为什么编译器抱怨下面代码中的类型不匹配:

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))
}

因此,问题是在此行doSomething(() => printSomeValue(str)),因为它是抱怨str的类型是string | undefined,而不是string . Playground

ymdaylpp

ymdaylpp1#

TypeScript不假设类型保护在回调中保持活动状态,因为做出这种假设是危险的(请注意这一点)。
你可以这样做:

if (str) {
  const newStr = str;
  doSomething(() => printSomeValue(newStr));
}

存储类型缩小的变量(str),在一个常量中告诉编译器,这个常量(newStr)将不会被改变.然后TypeScript会理解这一点。
我用一个例子来说明,为什么它是危险的:

let val = "A text for testing";

const myFunction = (value) => {
    console.log(value.length);
}

setTimeout(() => {
    val = undefined;
},3000)

if(val !== undefined){
    document.getElementById("clickable")
     .addEventListener("click",() => {myFunction(val)});
}

假设您有一个id为clickable的按钮,并且如果valnot undefined,您希望向其添加一个click事件侦听器。如果在触发setTimeOut回调之前单击该按钮,myFunction将正常运行,但在调用setTimeout函数之后,它会抛出错误(Cannot read properties of undefined(阅读'length'))。因为val已从更高的作用域更改,并且它会影响事件监听器回调行为。因此,条件:
if(val !== undefined)
无法保证val永远不会有undefined值。
但是,如果将val的值存储在newVal之类的常量中,并在事件侦听器中使用newVal,则问题将得到解决:

if(val !== undefined){
    const newVal = val;
    document.getElementById("clickable")
     .addEventListener("click",() => {myFunction(newVal)});
}

我希望它能帮助你。

相关问题