为什么打字稿无法在诸如map或find的数组方法中保留正确的类型信息

时间:2018-08-29 09:02:29

标签: typescript

在此示例中,在if范围内,p属性获取对象的类型,但是在箭头函数内部,它是对象或undefined

const o: { p?: { sp?: string } } = { p: {} }
if (o.p) {
  const b = ['a'].map(x => {
    if (o.p.sp) {
      return x
    }
  })
}

我在内部undefined处得到了一个可能为'if'的对象

为什么会这样?如何解决它或打字稿只是坏了?

1 个答案:

答案 0 :(得分:1)

这是由于TypeScript中使用strictNullChecks选项的控制流分析中的限制所致。没有该选项就没有错误。

假设以下简化示例:

const o: { p?: { sp?: string } } = { p: {} }
if (o.p) {
  if (o.p.sp) {
    // foo
  }
}

在这里,TypeScript编译器可以轻松地推断出自执行o.p以来,oif (o.p)均未更改。结果,它可以正常工作而没有任何错误。但是,一旦您引入更多的功能(例如函数调用),就会出现问题,这些功能可能会对o产生副作用。

有关详细信息,请参见Trade-offs in Control Flow Analysis。可能有助于理解此问题的注释示例之一是此代码:

if (token === SyntaxKind.ExportKeyword) {
    nextToken();
    if (token === SyntaxKind.DefaultKeyword) {
        // We have "export default"
    }
    ...
}

乍看之下,嵌套if子句是没有意义的,TypeScript会警告您。但是,nextToken()可能实际上会更改token,因此代码可能有意义。但是,对于编译器而言,很难真正正确地理解和解释这种情况。

通过将o.p.sp替换为o.p!.spo.p && o.p.sp,可以避免代码中的错误消息。