Javascript 当array.map返回不正确的类型时,忽略';过滤器';

Javascript 当array.map返回不正确的类型时,忽略';过滤器';,javascript,flowtype,Javascript,Flowtype,例如: let foo: number[]; foo = [1, 2, 3] .map(number => number === 1 ? number : null) .filter(number => number); 我得到一个错误: 8:.映射(编号=>编号===1?编号:空) ^无法将[…].map(…).filter(…)分配给foo,因为null不兼容 数组元素中的数字为[2] (你可以玩它) Flow查看“.map”部分并显示有关类型的错误,因为我有时返回n

例如:

let foo: number[];

foo = [1, 2, 3]
  .map(number => number === 1 ? number : null)
  .filter(number => number);
我得到一个错误:

8:.映射(编号=>编号===1?编号:空) ^无法将
[…].map(…).filter(…)
分配给
foo
,因为null不兼容 数组元素中的数字为[2]

(你可以玩它)

Flow查看“.map”部分并显示有关类型的错误,因为我有时返回
null
,它只需要数字。 但是,它忽略了我使用的“.filter”,它消除了所有
null


我如何在不使用“$FlowFixMe”的情况下解决它,因为我确实希望得到其他流错误。

这是因为您先使用map和
null
值分配给
整数数组,然后过滤它。因此,在您的第一个操作中,
map
,将在调用
filter
之前抛出一个错误

在这种情况下,您可以直接使用
filter

let foo: number[];

foo = [1, 2, 3]
  .filter(number => number == 1);

当您想
映射
+
过滤
时,
减少
可以简化您的工作:

let foo: number[];

foo = [1, 2, 3]
  .reduce((acc, number) => number == 1 ? acc.concat(number + 1) : acc, [])

从其他评论中,我看到这是对实际用例的简化。在您的示例中,
map
是多余的,并且具有误导性,您可以简单地使用
filter
实现同样的效果,但假设您确实需要该步骤

似乎您希望
foo
成为一个数字数组,或者使用null来支持
map
操作,然后您希望过滤掉null

您使用的是数组语法的缩写形式(
number[]
),如果要将数组元素键入为可选,则不能使用该语法。这将允许您指定
null
是允许的值

let foo: Array<?number>;

foo = [1, 2, 3]
  .map(number => number === 1 ? number : null)
  .filter(number => number);
您的筛选器将
number
强制为真实值,这将过滤掉等于零的有效数字(您的示例在这方面可能过于简化)


如果您不想使用数组排列(
..
),那么您可以使用
memo.push(number)
memo.concat([number])
,具体取决于您对
memo

的易变性的偏好,
.filter()
发生在
.map()
调用之后。也许可以使用
.reduce()
来代替。你想实现什么?@Pointy,我不能使用
.reduce()
,因为我想得到一个数组作为结果。@David
.reduce()
返回你想要的结果return@Pointy安德烈亚斯,你们说得对。(我只是在代码中快速地将单词
filter
替换为
reduce
,没有考虑太多)。在上面的示例中,我简化了实际用例。假设您确实需要“.map”返回带有一些计算的结果。下面是一个示例:
foo=[1,2,3].map(number=>number==1?number+1:null).filter(number=>number)
我知道它在
.filter
之前调用了.map,但是
foo
获取值作为
.map
.filter
的最终结果。事实上,您是对的,
foo
map
filter
的结果之后获取值。我的猜测是
flow
不支持checker-to-chained函数。无论如何,你可以像我上面所做的那样使用
reduce
。谢谢@guijob,这样可以工作,我不会出错。唯一的问题是,对我来说,它使它不那么可读。因为我的目的不是减少原始阵列。在实际情况中,我在
.map
部分进行大量计算,很少返回
null
。我希望我能教Flow把“过滤器”考虑在内。
let foo: Array<number | null>;

foo = [1, 2, 3]
  .map(number => number === 1 ? number : null)
  .filter(number => number);
let foo: Array<number | null>;

foo = [1, 2, 3]
  .map(number => number === 1 ? number : null)
  .filter(number => typeof number === 'number');
let foo: Array<number | null>;

foo = [1, 2, 3]
  .reduce((memo, number) => {
    if (number === 1) {
      return [ ...memo, number ];
    }
    return memo;
  }, []);