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

TypeScript中zip与unzip数组函数的返回类型如何定义?

TypeScript 数组转置函数zip/unzip的精准类型标注实现

你现有代码的运行时逻辑没有问题,要实现你期望的类型推导效果,不需要使用any,借助TypeScript的元组类型、映射类型、条件类型就可以完成严格的类型标注,完整实现如下:

function range(size: number, startAt: number = 0): ReadonlyArray<number> {
  return [...Array(size).keys()].map((i) => i + startAt);
}

// 映射zip单行结果的元组类型,长度不足的数组位置自动补undefined类型
type ZipRow<T extends readonly (readonly unknown[])[]> = {
  [K in keyof T]: T[K] extends readonly (infer V)[] ? V | undefined : never
};

function zip<T extends readonly (readonly unknown[])[]>(...arrays: T): ZipRow<T>[] {
  const maxLength = Math.max(...arrays.map(x => x.length));
  return range(maxLength).map(i =>
    range(arrays.length).map((_, k) => arrays[k][i])
  ) as ZipRow<T>[];
}

// 递归处理unzip的列类型聚合
type UnzipRows<T extends readonly unknown[], Acc extends unknown[][] = []> =
  T extends readonly [infer First extends unknown[], ...infer Rest extends unknown[][]]
    ? UnzipRows<Rest, {
        [K in keyof Acc | keyof First]:
          K extends keyof Acc
            ? K extends keyof First ? [...Acc[K], First[K]] : Acc[K]
            : K extends keyof First ? [First[K]] : never
      }>
    : { [K in keyof Acc]: Acc[K][number][] };

function unzip<T extends readonly unknown[]>(array: readonly T[]): UnzipRows<T> {
  const maxLength = Math.max(...array.map(x => x.length));
  return array.reduce(
    (acc, val) => {
      val.forEach((v, i) => acc[i].push(v));
      return acc;
    },
    range(maxLength).map(() => [])
  ) as UnzipRows<T>;
}

类型推导效果验证

  • 调用zip([1, 2, 3], ["a", "b"])时,返回值自动推导为[number | undefined, string | undefined][],和预期一致;如果输入数组长度不一致,短数组缺失的位置会自动带上undefined类型,不会出现隐式类型漏洞。
  • 调用unzip([[1, "a"], [2, "b"], [3, undefined]])时,返回值自动推导为[number[], (string | undefined)[]],符合要求。

注:你问题中写的unzip([1, "a"], [2, "b"], [3, undefined])调用方式和你给出的unzip函数定义不匹配,你写的unzip是接收元组数组作为单个参数,不是接收多个独立参数,如果需要多参数调用的版本,把unzip的参数改成和zip一致的rest参数写法,对应调整泛型入参即可。

说明

代码中少量的as类型断言属于合理收敛:TypeScript的类型系统无法静态推导map、reduce这类高阶函数运行时生成的元组结构,这里断言的目标类型完全由输入参数的泛型推导而来,不会丢失类型安全性,比直接标注any的实现严格很多。
该类型实现支持任意长度的输入参数,不需要为不同参数个数手动写函数重载,通用性更强。

内容的提问来源于stack exchange,提问作者fff

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:01:05