求实现支持可变长度元组的TypeScript数组divide函数类型定义
实现支持任意数量类型守卫的数组divide方法
需求是为数组扩展一个divide方法,接收任意数量的类型守卫/类类型守卫函数,将原数组按守卫顺序划分成对应数量的类型化数组组成的元组,不匹配任何守卫的元素直接丢弃。示例用法如下:
const [typeAs, typeBs, typeCs] = myArr.divide(isTypeA, isTypeB, isTypeC); const [typeFs] = myArr.divide(isTypeF); const [typeAs, typeFs, typeDs, typeCs, typeXYZs] = myArr.divide(isTypeA, isTypeF, isTypeD, isTypeC, isTypeXYZ); // 支持任意数量守卫参数
之前已实现支持最多3个守卫的版本,但需要扩展为支持任意数量参数,核心难点在于编写能匹配任意长度元组的类型签名。
完整解决方案
1. 类型定义
通过TypeScript的泛型元组和映射类型,可以实现对任意数量守卫的类型推导:
// 定义类型守卫的通用类型,支持类型谓词或普通布尔返回函数 type TypeGuard<T> = ((input: unknown) => input is T) | ((input: unknown) => boolean); // 映射守卫元组到对应的数组元组类型 type GuardToArray<T extends TypeGuard<any>[]> = { [K in keyof T]: T[K] extends TypeGuard<infer U> ? U[] : never; }; // 扩展Array接口,添加divide方法的类型声明 declare global { interface Array<T> { divide<G extends TypeGuard<any>[]>(...guards: G): GuardToArray<G>; } }
2. 方法实现
实现部分通过遍历数组元素,按守卫顺序依次匹配,将元素推入对应分组数组:
Array.prototype.divide = function <G extends TypeGuard<any>[]>(...guards: G) { // 初始化对应数量的空数组组成的元组 const result = guards.map(() => []) as GuardToArray<G>; this.forEach(item => { // 遍历守卫,找到第一个匹配的分组 for (let i = 0; i < guards.length; i++) { if (guards[i](item)) { result[i].push(item); break; // 匹配到第一个守卫后停止检查 } } // 不匹配任何守卫的元素直接丢弃 }); return result; };
内容的提问来源于stack exchange,提问作者jbailie1991
相关产品推荐
相关产品推荐

