You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 01:17:57