TypeScript中如何根据类型过滤联合类型数组?
解决TypeScript联合类型数组的类型判断与过滤问题
对于TypeA[] | TypeB[]这种联合类型数组,你可以通过类型守卫来收窄类型,从而准确判断数组属于哪种类型并进行过滤。下面是具体实现方案:
方案1:使用自定义类型守卫函数
自定义类型守卫能让代码逻辑更清晰,尤其适合需要多次判断的场景:
interface TypeA { attribute1: string attribute2: string } interface TypeB { attribute3: string attribute4: string } // 判断数组是否为TypeA[]类型 function isTypeAArray(arr: unknown): arr is TypeA[] { // 先判断是否为数组,再检查第一个元素是否包含TypeA的特征属性 return Array.isArray(arr) && arr.length > 0 && 'attribute1' in arr[0]; } // 判断数组是否为TypeB[]类型 function isTypeBArray(arr: unknown): arr is TypeB[] { return Array.isArray(arr) && arr.length > 0 && 'attribute3' in arr[0]; } function filterFunc(obj: TypeA[] | TypeB[]) { // 处理空数组的特殊情况(空数组同时符合两种类型,可根据需求调整逻辑) if (obj.length === 0) { return []; } if (isTypeAArray(obj)) { return obj.filter(item => item.attribute1 === 'test'); } if (isTypeBArray(obj)) { return obj.filter(item => item.attribute3 === 'something'); } // 兜底返回(理论上不会走到这里,因为输入类型是明确的联合类型) return []; }
方案2:直接在条件中进行类型收窄
如果不需要复用判断逻辑,可以直接在if条件里通过属性检查完成类型收窄:
interface TypeA { attribute1: string attribute2: string } interface TypeB { attribute3: string attribute4: string } function filterFunc(obj: TypeA[] | TypeB[]) { if (obj.length > 0 && 'attribute1' in obj[0]) { // 此时TypeScript会自动将obj推断为TypeA[] return obj.filter(item => item.attribute1 === 'test'); } if (obj.length > 0 && 'attribute3' in obj[0]) { // 此时TypeScript会自动将obj推断为TypeB[] return obj.filter(item => item.attribute3 === 'something'); } // 空数组或无法判断时返回空数组 return []; }
关键说明
- 为什么要检查数组长度?因为空数组
[]同时满足TypeA[]和TypeB[]的类型约束,直接检查属性会导致报错,所以需要先处理空数组场景。 - 类型收窄的核心:TypeScript会根据
in操作符的检查结果,自动推断变量的具体类型,从而允许你访问对应类型的属性(比如item.attribute1或item.attribute3)。
内容的提问来源于stack exchange,提问作者nassim hajjaji
相关产品推荐
相关产品推荐

