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

TypeScript中Promise.all的类型推断原理是什么?自定义实现为何报错?

关于TypeScript对Promise.all的类型定义与自定义实现问题解答

内置Promise.all的类型推断原理

你看到的单泛型签名只是Promise.all的其中一个重载,TypeScript为了支持传入不同类型的Promise,实际上做了两层设计:

  • 首先是针对固定长度的短元组做了专门的重载,比如2个、3个、4个参数的场景,每个重载都会单独匹配每个位置的Promise类型,精准返回对应类型的元组
  • 对于更长的参数,TypeScript使用可变元组泛型做统一处理,会遍历传入的Promise元组的每一个位置,单独提取每个Promise的resolve值类型,最终把这些类型按原顺序组合成新的元组作为返回值的泛型参数

所以即使传入不同类型的Promise,TypeScript也能按位置推断出每一项的准确类型,不会把所有类型合并成联合类型。

自定义promiseAll报错的原因

你写的实现用了统一的泛型T来定义整个Promise数组的返回值类型:function<T>(promises: Promise<T>[]): Promise<T[]>,这就要求所有传入的Promise的resolve值必须是同一个类型。当你同时传入Promise<number>和Promise<string>时,TypeScript只能把T推断为number | string,返回值就变成了(number | string)[],和你预期的按位置匹配的[number, string]元组类型不符,自然会抛出类型错误。

自定义promiseAll的修复方案

把泛型改成可变元组形式,让TypeScript可以逐个匹配每个位置的Promise类型:

const promiseAll = function<T extends readonly unknown[]>(promises: [...{ [K in keyof T]: Promise<T[K]> }]): Promise<[...T]> {
  const results: unknown[] = [];
  let completedCount = 0;
  return new Promise(function (resolve, reject) {
    promises.forEach(function(promise, index) {
      promise.then(function (value) {
        results[index] = value;
        completedCount += 1;
        if(completedCount === promises.length) {
          resolve(results as T);
        }
      }).catch(function (error) {
        reject(error);
      });
    });
  });
}

修改后再调用promiseAll([promise1, promise2]),返回值就会被正确推断为Promise<[number, string]>,和内置Promise.all的表现完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 23:36:00