Flow无法识别回调内的细化

sor*_*nbs 4 flowtype

此代码通过流检查:

/* @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))
Run Code Online (Sandbox Code Playgroud)

以下获取空检查错误

/* @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))
Run Code Online (Sandbox Code Playgroud)

错误:

property `length`. Property cannot be accessed on possibly null value
Run Code Online (Sandbox Code Playgroud)

显然列表不能null这样,必须有一些代码结构,使流程无法识别这一点.

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

Nik*_*ita 7

基本上,Flow不知道您的类型细化(空检查)将在() => list.length执行时保留.在回调流程中只查看列表的类型 - 它表示它可以为null.

第一个和第二个片段之间的区别在于,在第二个片段list中跨越了一个函数边界 - 您在与其细化其类型的函数不同的函数中使用它.

一种解决方案是将list.length提取到变量中,并在回调中使用该变量.

var length = list.length;
return Promise.resolve().then(() => length)
Run Code Online (Sandbox Code Playgroud)

这可能也有效:

var list2: Array<string> = list;
return Promise.resolve().then(() => list2.length)
Run Code Online (Sandbox Code Playgroud)

请注意,即使对于立即调用的回调,例如使用map或时,此问题也存在forEach.关于flow的github有一个问题,但是在快速搜索之后我找不到它.