题目
假如我们有一个 Promise 对象,这个 Promise 对象会返回一个类型。在 TS 中,我们用 Promise 中的 T 来描述这个 Promise 返回的类型。请你实现一个类型,可以获取这个类型。
例如:Promise<ExampleType>,请你返回 ExampleType 类型。
更具体的例子:
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 }
// 返回 string
MyAwaited<X>
// 返回 { field: number }
MyAwaited<Y>
// 返回 string | number
MyAwaited<Z>
// 返回 string | boolean
MyAwaited<Z1>
// 返回 number
MyAwaited<T>
// 报错,number 不是 Promise 类型
MyAwaited<number>
原题链接
思路
渐进式解题
从简单到复杂,分步骤依次解决:
- 必须接收一个
Promise类型,通过extends在接收参数时限制。
type MyAwaited<T extends Promise<unknown>> = ...
- 取出
Promise中的类型。
通过 infer 推断出来,用 X 表示,在后续语句中使用。
type MyAwaited<T extends Promise<unknown>> = T extends Promise<infer X> ...
- 如果
X是一个Promise,那么需要继续解构,通过递归调用MyAwaited来实现。 - 如果
X不是一个Promise,那么直接返回X即可。
type MyAwaited<T extends Promise<unknown>> = T extends Promise<infer X> ?
(X extends Promise<unknown> ? MyAwaited<X> : X)
:
T;
实现
综上所述,最终的类型工具 MyAwaited 实现为:
type MyAwaited<T extends Promise<unknown>> = T extends Promise<infer X> ?
(X extends Promise<unknown> ? MyAwaited<X> : X)
:
T;