题目描述
假如我们有一个 Promise 对象,这个 Promise 对象会返回一个类型。在 TS 中,我们用 Promise 中的 T 来描述这个 Promise 返回的类型。请你实现一个类型,可以获取这个类型。
例如:Promise<ExampleType>,请你返回 ExampleType 类型。
type ExampleType = Promise<string>
type Result = MyAwaited<ExampleType> // string
题解
// ============= Test Cases =============
import type { Equal, Expect } from './test-utils'
type X = Promise<string>
type Y = Promise<{ field: number }>
type Z = Promise<Promise<string | number>>
type Z1 = Promise<Promise<Promise<string | boolean>>>
type T = { then: (onfulfilled: (arg: number) => any) => any }
type cases = [
Expect<Equal<MyAwaited<X>, string>>,
Expect<Equal<MyAwaited<Y>, { field: number }>>,
Expect<Equal<MyAwaited<Z>, string | number>>,
Expect<Equal<MyAwaited<Z1>, string | boolean>>,
Expect<Equal<MyAwaited<T>, number>>,
]
// @ts-expect-error
type error = MyAwaited<number>
// ============= Your Code Here =============
type MyAwaited<T extends PromiseLike<any>> =
T extends PromiseLike<infer U>
? U extends PromiseLike<any>
? MyAwaited<U>
: U
: never
1、使用T extends PromiseLike<any>对传入的类型参数T进行约束
2、PromiseLike是 TypeScript 提供的一个内置类型,它实际上定义了一种类似Promise的接口规范。它的接口定义如下:
interface PromiseLike<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseLike<TResult1 | TResult2>;
}
借助PromiseLike使得MyAwaited不仅可以处理标准的Promise类型,还能处理实现了then方法的其他自定义类型(例如类型T)
3、利用infer U进行类型推断以及递归提取参数
infer U的作用是从传入的PromiseLike类型中提取出其then方法对应的回调函数所返回的类型
接着,进一步判断U是否依旧是一个PromiseLike类型
如果是,则通过递归调用MyAwaited<U>再次解析嵌套的PromiseLike,直到提取的U不是PromiseLike类型
如果U不是PromiseLike类型,返回U