只有在承诺链中:"在未定义的情况下无法访问属性"

时间:2017-06-27 17:12:42

标签: javascript flowtype

Please refer to this example.

function f(a ?: Array<string>) {
  a = a || [];
  a.map // Here it is ok
  return Promise.resolve()
    .then(() => a.map) // THROWS, WHY?
}

2 个答案:

答案 0 :(得分:3)

Flow的类型改进是保守的。这意味着它invalidates them在无法确定它们将会持有的情况下积极地进行。{/ p>

在这种情况下,Flow会看到a已被重新分配,因此它不能是null / undefined。但是,它不会进行分析,知道始终将是null / undefined - 就其在此处所知,以后的某些任务可以重新进行将其分配给null / undefined

它也不知道何时会调用传递给.then的回调。因此,它保守地使改进无效。

请注意,此问题并非特定于Promise。只要非const变量应用了一个细化,它就会发生,稍后在闭包中使用它。在封闭内部,细化将被删除。

简单的解决方法是使用const。然后,Flow知道应用的任何类型细化将始终保持,因为永远不能重新分配变量:

function f(a_ ?: Array<string>) {
  const a = a_ || [];
  a.map // Here it is ok
  return Promise.resolve()
    .then(() => a.map) // THROWS, WHY?
}

答案 1 :(得分:-2)

这是因为在你的函数定义中你有:

function f(a ?: Array<string>) {

这意味着a的类型是一个字符串数组但它可以为空?:)。它的值可以为null(或未定义)。

虽然从您的代码中可以看出,anull(或未定义)覆盖,但它被空数组覆盖。但它的类型仍然是一个可以为空的字符串数组。

当编译器尝试编译此行时:

.then(() => a.map) // THROWS, WHY?

它认为a可能为null(或未定义),因此会报错。

如果删除函数参数类型中的问号?,编译器会知道a不能为空,因此可以正常工作!

PS:如果需要,您可以将a = a || [];移动到调用函数f的函数。