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],重点是返回值的内容,我们都知道,javascript 中 Promise.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] 类型。