Flow忽略filter操作,map返回非预期类型时报错的解决办法
解决Flow中map后filter仍报类型不兼容的问题
嘿,这个问题我之前也碰到过——Flow的类型推断在这里有个小局限,它没办法自动识别filter操作已经把所有null值都过滤掉了。不过不用$FlowFixMe也有几个靠谱的解决办法:
方法一:给filter添加类型守卫函数
Flow需要明确知道你的filter回调是在做类型过滤,所以可以写一个带类型断言的守卫函数,让Flow清楚过滤后剩下的都是number类型:
const isNumber = (value: mixed): value is number => { return typeof value === 'number'; }; const foo: number[] = [1, 2, 3].map(number => number === 1 ? number : null).filter(isNumber);
这里的value is number是Flow的类型守卫语法,相当于告诉Flow:“当这个函数返回true时,参数肯定是number类型”,这样filter后的数组类型就会被正确推断为number[],不会再报类型不兼容的错误。
方法二:用reduce一步完成映射+过滤
如果不想额外写守卫函数,也可以用reduce把映射和过滤合并成一步,这样Flow能直接跟踪到最终的数组类型:
const foo: number[] = [1, 2, 3].reduce((acc, number) => { if (number === 1) { acc.push(number); } return acc; }, [] as number[]);
这里通过[] as number[]明确初始累加器的类型,Flow就能确定acc始终是number[]类型,自然不会出现null的类型冲突。
方法三:显式断言(谨慎使用)
如果你百分百确定filter会把所有null都去掉,也可以给map的结果加个类型断言,但这种方式不如前两种安全——要是后续修改map逻辑引入了其他非number值,Flow不会帮你检查出来:
const foo: number[] = ([1, 2, 3].map(number => number === 1 ? number : null) as Array<number>).filter(Boolean);
所以更推荐前两种方法,尤其是方法一,类型守卫既能解决类型问题,还能让代码的意图更清晰,也符合Flow的类型系统设计思路。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

