如何从对象数组的单个对象字段类型中过滤null?
解决TypeScript中合并数组后移除类型中的null问题
问题场景
我们有两个数组需要合并,其中nums的类型被标注为(number | null)[]但实际不存在null元素:
const strs = ['zero', 'one', 'two', 'three', 'four']; // 模拟类型为`(T | null)[]`但实际无null元素的场景 const nums: (number | null)[] = [0, 1, 2, 3, 4]; const zipped = strs.map((str, i) => ({ str, num: nums[i] }));
合并后的zipped类型为{ str: string, num: number | null }[],但我们确定num绝不会为null,需要从类型中移除null。
为什么之前的方法无效
直接使用filter或者针对num的类型谓词函数,TypeScript无法自动推断整个数组元素的类型变化——因为类型谓词只作用于num字段,而非整个对象。
解决方案
1. 为数组元素编写类型谓词函数
针对整个对象编写类型谓词,明确判断num不为null时,元素的类型是{ str: string; num: number }:
const isNumNonNull = (item: { str: string; num: number | null }): item is { str: string; num: number } => { return item.num !== null; }; const checkedNull = zipped.filter(isNumNonNull); // checkedNull的类型为{ str: string; num: number }[]
2. 类型断言(谨慎使用)
如果能完全保证数据安全,可以直接用类型断言强制修改数组类型:
const checkedNull = zipped.filter(({ num }) => num !== null) as { str: string; num: number }[];
3. 从源头修正类型
既然确定nums中没有null元素,在合并前就将其类型断言为number[],这样合并后的zipped类型直接符合预期:
const numsAsserted = nums as number[]; const zipped = strs.map((str, i) => ({ str, num: numsAsserted[i] })); // zipped的类型为{ str: string; num: number }[]
内容的提问来源于stack exchange,提问作者eloy
相关产品推荐
相关产品推荐

