type-challenges:Promise.all

37 阅读2分钟

Promise.all

问题描述

给函数PromiseAll指定类型,它接受元素为 Promise 或者类似 Promise 的对象的数组,返回值应为Promise<T>,其中T是这些 Promise 的结果组成的数组。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise<string>((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});
​
// 应推导出 `Promise<[number, 42, string]>`
const p = PromiseAll([promise1, promise2, promise3] as const)
// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'const promiseAllTest1 = PromiseAll([1, 2, 3] as const)
const promiseAllTest2 = PromiseAll([1, 2, 3])
const promiseAllTest3 = PromiseAll([1, 2, Promise.resolve(3)] as const)
const promiseAllTest4 = PromiseAll([1, 2, Promise.resolve(3)])
const promiseAllTest5 = PromiseAll<Array<number | Promise<number>>>([1, 2, 3])
const promiseAllTest6 = PromiseAll([
  1,
  2,
  Promise.resolve(Promise.resolve(Promise.resolve(3)))
])
type cases = [
  Expect<Equal<typeof promiseAllTest1, Promise<[1, 2, 3]>>>,
  Expect<Equal<typeof promiseAllTest2, Promise<[number, number, number]>>>,
  Expect<Equal<typeof promiseAllTest3, Promise<[1, 2, number]>>>,
  Expect<Equal<typeof promiseAllTest4, Promise<[number, number, number]>>>,
  Expect<Equal<typeof promiseAllTest5, Promise<number[]>>>,
  Expect<Equal<typeof promiseAllTest6, Promise<[number, number, number]>>>,
]
​
// ============= Your Code Here =============
// 答案1
declare function PromiseAll<T extends any[]>(
  values: readonly [...T]
): Promise<{
  [key in keyof T]: Awaited<T[key]>
}>
// 答案2
type PromiseFlat<T> = T extends Promise<infer R> ? PromiseFlat<R> : T
declare function PromiseAll<T extends any[]>(
  values: readonly [...T]
): Promise<{
  [K in keyof T]: PromiseFlat<T[K]>
}>

这道题有些难度,首先需要理解 Promise,知道其原理和如何实现,这是前提,其次,需要理解 [1, 2, 3] as const[1, 2, 3] 的区别,前者的类型即为其本身,后者的类型为 [number, number, number] 。先看答案1,这里首先需要约束形参的类型必须为数组 T extends any[]values 的值是 readonly 是因为,这里的 [1, 2, 3] as const 得到的就是 readonly [1, 2, 3],重点是返回值的内容,我们都知道,javascriptPromise.all 方法得到的返回值都是 Promise ,这里遍历数组中的每一项,每一项的值应该也是返回一个 Promise ,其次需要继续判断数组中的每一项本身是不是 Promise ,如果是则继续判断该 Promise 的形参是不是 Promise,比如测试用例6,所以返回值是 Promise<{[key in keyof T]: Awaited<T[key]>}>Awaited<T[key]> 得到的就是 T[key] 的类型。你也可以自己尝试得到 T[key] 的类型,在答案2中 使用递归判断当前键值是否是 Promise 类型,如果是,则继续递归,直到拿到最内层的 T[key] 类型。