Flow 无法识别回调中的细化

Flow doesn't recognise refinement inside callback

此代码通过流检查:

/* @flow */

function test (list: ?Array<string>): Promise<number> {
  if(list !== null && list !== undefined) {
    return Promise.resolve(list.length)
  } else {
    return Promise.resolve(0)
  }
}

console.log(test(null))

而以下得到空检查错误

/* @flow */

function test (list: ?Array<string>): Promise<number> {
  if(list !== null && list !== undefined) {
    return Promise.resolve().then(() => list.length)
  } else {
    return Promise.resolve(0)
  }
}

console.log(test(null))

错误:

property `length`. Property cannot be accessed on possibly null value

很明显list不能是null所以代码结构一定有什么东西让flow无法识别这个。

我想了解我遇到的限制以及如何解决它。谢谢!

基本上,Flow 不知道您的类型细化(空检查)将在执行 () => list.length 时保持不变。在该回调中,Flow 仅查看列表的类型——它表示它可以为 null。

第一个和第二个代码段的区别在于,在第二个代码段中,list 跨越函数边界 – 您在不同的函数中使用它,而不是在优化其类型的地方使用它。

一个解决方案是将 list.length 提取到一个变量中,然后在回调中使用该变量。

var length = list.length;
return Promise.resolve().then(() => length)

这也可能有效:

var list2: Array<string> = list;
return Promise.resolve().then(() => list2.length)

请注意,即使是立即调用的回调也存在此问题,例如使用 mapforEach 时。流github上有一个关于这个的问题,但我快速搜索后没有找到它。