如何将TypeScript笛卡尔积迭代器改为完全泛型实现?
实现完全泛型的TypeScript笛卡尔积迭代器
原代码实现了一个笛卡尔积迭代器,但仅支持固定3个输入数组的类型注解,而函数逻辑本身可以处理任意长度的输入数组。我们需要改造它,让类型系统能自动适配任意数量的输入数组,同时保留每个元素的类型信息。
完整泛型实现代码
export function* productIterator<T extends any[]>( ...arr: T ): Generator<{ [K in keyof T]: T[K] extends (infer U)[] ? U : never }> { const lengths = arr.map(component => component.length); const total = lengths.reduce((prod, len) => prod * len, 1); for (let totalIndex = 0; totalIndex < total; totalIndex++) { const product: unknown[] = []; let reducedIndex = totalIndex; for (const iter of arr) { product.push(iter[reducedIndex % iter.length]); reducedIndex = Math.floor(reducedIndex / iter.length); } yield product as { [K in keyof T]: T[K] extends (infer U)[] ? U : never }; } }
关键类型逻辑说明
- 泛型约束
T extends any[]:限定输入参数是任意长度的数组元组,每个元素对应一种类型的数组(比如[Colors[], Sizes[]]或[A[], B[], C[], D[]]) - 动态返回类型推导:通过
{ [K in keyof T]: T[K] extends (infer U)[] ? U : never }遍历元组的每个位置,将数组类型T[K]提取出其元素类型U,最终生成对应长度的结果元组类型(比如输入[Colors[], Sizes[]]时,返回类型为[Colors, Sizes]) - 类型断言必要性:函数内部的
product数组无法被TypeScript自动推断为精确的元组类型,因此需要通过断言匹配返回类型
使用示例
// 3个输入数组的场景 type Colors = 'blue' | 'red'; const colors: Colors[] = ['blue', 'red']; type Sizes = 'small' | 'medium' | 'large'; const sizes: Sizes[] = ['small', 'medium', 'large']; type Fits = 'turtleneck' | 'tank'; const fits: Fits[] = ['turtleneck', 'tank']; for (const [color, size, fit] of productIterator(colors, sizes, fits)) { console.log(color, size, fit); // 每个变量都有精确的类型提示 } // 2个输入数组的场景 type Shapes = 'circle' | 'square'; const shapes: Shapes[] = ['circle', 'square']; type Materials = 'wood' | 'plastic'; const materials: Materials[] = ['wood', 'plastic']; for (const [shape, material] of productIterator(shapes, materials)) { console.log(shape, material); // 类型推导正常 } // 4个输入数组的场景 type Brands = 'nike' | 'adidas'; const brands: Brands[] = ['nike', 'adidas']; type Genders = 'male' | 'female'; const genders: Genders[] = ['male', 'female']; for (const [brand, gender, shape, material] of productIterator(brands, genders, shapes, materials)) { console.log(brand, gender, shape, material); // 类型信息完整保留 }
内容的提问来源于stack exchange,提问作者Kaia
相关产品推荐
相关产品推荐

