首页 > 解决方案 > typescript 如何输入 Promise.all()

问题描述

typescript 是如何键入 Promise.all() 在解析出来的值数组中,typescript 是如何能够推断出每一项的类型呢?我在 Promise.all() 的类型签名中只看到一个 Generic T,但为什么我能够传入解析为不同类型值的承诺?

详细地说,为什么我的 promiseAll 实现会抛出 typescript 类型错误,但内置的实现却像魔术一样工作?

const promiseAll = function<T>(promises: Promise<T>[]): Promise<T[]> {
  const results: T[] = [];
  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);
        }
      }).catch(function (error) {
        reject(error);
      });
    });
  });
}

const promise1 = new Promise<number>(resolve => setTimeout(() => { resolve(1) }, 500));
const promise2 = new Promise<string>(resolve => setTimeout(() => { resolve("a") }, 500));



async function main() {
    const [value1, value2] = await Promise.all([promise1, promise2]);
    const [myValue1, myValue2] = await promiseAll([promise1, promise2]);
}

main();

标签: javascripttypescriptes6-promise

解决方案


具有 11 个重载的TypeScript 类型Promise.all,但这种方法最多只允许PromiseLike传入有限数量的不同类型的对象。不过,其中一个重载能够处理填充了一致类型PromiseLike对象的任意长度的数组。以下是两个重载示例:

Promise.all<T1, T2, T3, T4>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<[T1, T2, T3, T4]>
Promise.all<T>(values: readonly (T | PromiseLike<T>)[]): Promise<T[]>

具有独立类型参数的Promise.all重载似乎只支持参数中最多 9 个不同类型的元素values

您作为示例给出的代码与上面的第二个重载非常匹配,但具有相同的限制,因为它仅Promise在传递给的数组中每个的类型相同时才有效Promise.all

如果您告诉 TypeScript 您将类型数组传递Promise<number | string>[]给,您的示例将编译PromiseAll,因为这样您的所有Promises 都将被视为具有相同的类型。当然,您返回的数组将是类型(number | string)[],并且您不知道哪个元素具有哪种类型。


推荐阅读