如果我将检查放入变量中,为什么流程会抱怨?

Why does flow complain if I put the checking into a variable?

我想使用变量来验证数组。所以我这样做了:

const length = array ? array.length : 0;

if (length) {
   array.map(_ => _.displayName);
}

为此我得到一个流程错误:Cannot call 'array.map' because propertymapis missing in undefined [1].Flow(InferError)

如果不知道 array 的类型,很难说出您要做什么。

Why does flow complain if I put the checking into a variable?

一般来说,这在流程中不起作用。流程的细化非常有限。 documentation on refinement 基本上列出了支持的每一种细化形式,检查 length 不是其中之一。你不能真正做一些事情,比如把某些东西是某种类型的事实带到以后。看,例如:

// Let's assume `array` is `Array<any> | null` for the sake of this example
const array: Array<any> | null = ([]: any);

我们可以通过这样做将 array 细化为一个数组:

if (Array.isArray(array)) {
  // here, _within this block,_ `array` is of type `Array<any>`
  (array: Array<any>);
}

// Here, `array` is `Array<any> | null` again
(array: Array<any>); // Error! Cannot cast `array` to array type 
  // because null [1] is incompatible with array type [2].

我们也可以反其道而行之:

if (array === null) {
  // here, array is `null`
  (array: null);
} else {
  // and because this is in an `else` block, flow knows that
  // array is `Array<any>` here
  (array: Array<any>);
}

// ...and now it's back to `Array<any> | null` again:
(array: null); // Error! Cannot cast...

因为我们联盟只有两个选择,一个是真实的 和一个虚假的,我们可以检查 array 的真实性 完善它:

if (array) {
  (array: Array<any>);
} else {
  (array: null);
}

那么我们不能做的事情呢?

Flow 不够聪明,无法理解 arrayIsArray 携带精炼信息 array:

const arrayIsArray = Array.isArray(array);
if (arrayIsArray) {
  (array: Array<any>); // Error! Cannot cast...
}

一般来说,优化的范围是 他们出现的声明。

(Try Flow)