Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么TypeScript希望在回调中进行另一个未定义的检查?_Typescript - Fatal编程技术网

为什么TypeScript希望在回调中进行另一个未定义的检查?

为什么TypeScript希望在回调中进行另一个未定义的检查?,typescript,Typescript,有时我会偶然发现: if (obj.needle) { // obj = { needle?: string } console.log(obj.needle) // no error here matches((haystack) => { return haystack.needle === obj.needle // Error: Object is possibly 'undefined'. }) } 似乎TypeScript需要在回调函数中进行另一次检查。

有时我会偶然发现:

if (obj.needle) { // obj = { needle?: string }
  console.log(obj.needle) // no error here

  matches((haystack) => {
    return haystack.needle === obj.needle // Error: Object is possibly 'undefined'.
  })
}
似乎TypeScript需要在回调函数中进行另一次检查。
我想知道为什么?(b)如何优雅地修复此问题-无需再次检查,因为它不是一个异步函数,
obj.needle
不可能突然
“未定义”

调用toLowerCase以实际获取您所说的错误:

事情就是这样发生的:

const obj: {needle?: string} = {needle: "hello"};

if (obj.needle) { // obj = { needle?: string }
    console.log(obj.needle) // no error here

    matches((haystack) => {
        // Error: Object is possibly 'undefined'.
        return obj.needle.toLowerCase() === haystack.needle.toLowerCase() 
    })
}

function matches(func: (haystack: {needle: string}) => boolean) {
    obj.needle = undefined;
    func({ needle: "whatever" });
}

Typescript不知道
匹配
仅在定义了
obj
时调用此回调。据TS所知,
matches
可以挂起该函数,并在以后的某个随机时间调用它,而
obj
可以是任何东西。或
匹配项
也可以在调用回调之前更改
obj
。据TS所知,在调用此回调之前,
obj
有很多方法可以改变

有几种可能的解决办法。单行修复只是创建TS知道无法更改的对象的常量副本:

if (obj.needle) { // obj = { needle?: string }
  console.log(obj.needle) // no error here

  const constObj = obj
  matches((haystack) => {
    return haystack.needle === constObj.needle
  })
}
另一个选项是创建一个生成回调的函数(本质上是相同的,但代码多一点):


编译器无法确定在调用回调时变量是否未定义。虽然在调用
匹配项时它肯定不是未定义的,但它反过来又不能确定何时调用它(至少从编译器的角度来看)。你确定它是在抱怨
obj
而不是
haystack
?当我尝试你的代码时,我没有typescript错误。试试看。@Alejandro但是
matches
(我的意思是回调)立即被调用,就在
console.log()之后,TypeScript认为在这两者之间发生了什么神奇的事情?TS不知道
matches
只在定义了
obj
时调用这个回调。据TS所知,
matches
可以挂起该函数,并在以后的某个随机时间调用它,而
obj
可以是任何东西。或
匹配项
也可以在调用回调之前更改
obj
。有很多事情TS不知道。@kraftwer1您知道,因为您知道
匹配的确切实现,但编译器不知道这一事实,它可能现在就调用它,或者它可能调用得太晚,甚至根本不知道。正是由于缺乏魔力才触发了这一错误。虽然您确信错误不会因为代码的形状而发生,但编译器还不够聪明,无法实现。与其他语言一样,开发人员通常比编译器更了解某些事实。
const createMatcher = obj => haystack => {
    return haystack.needle === obj
}

if (obj?.needle) { // obj = { needle?: string }
  console.log(obj.needle) // no error here

  matches(createMatcher(obj))
}