问题 #
键入函数PromiseAll
,它接受PromiseLike对象数组,返回值应为Promise<T>
,其中T
是解析的结果数组。
const promiseAllTest1 = PromiseAll([1, 2, 3] as const) // Promise<[1, 2, 3]>
const promiseAllTest2 = PromiseAll([1, 2, Promise.resolve(3)] as const) // Promise<[1, 2, number]>
const promiseAllTest3 = PromiseAll([1, 2, Promise.resolve(3)]) // Promise<[number, number, number]>
解答 #
declare function PromiseAll<T extends any[]>(values: readonly [...T]): Promise<{
[K in keyof T]: T[K] extends Promise<infer R>? R: T[K]
}>
拆分 #
- 首先定义一个函数参数限定为数组
T extends any[]
- 因为需要接受只读的数组,需要用
readonly [...T]
标记 - 返回的是一个
Promise
包裹的对象 - 需要确认属性值是否是
Promise
包裹后的对象 - 如果是
Promise
包裹后的对象需要拆包,用Promise<infer R>
获取类型 - 然后用索引签名来获取一个新的类型对象