「TS类型体操00189」实现 Awaited

139 阅读1分钟

题目

假如我们有一个 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>

原题链接

实现 MyAwaited

思路

渐进式解题

从简单到复杂,分步骤依次解决:

  1. 必须接收一个Promise类型,通过 extends 在接收参数时限制。
type MyAwaited<T extends Promise<unknown>> = ...
  1. 取出 Promise 中的类型。

通过 infer 推断出来,用 X 表示,在后续语句中使用。

type MyAwaited<T extends Promise<unknown>> = T extends Promise<infer X> ...
  1. 如果 X 是一个 Promise,那么需要继续解构,通过 递归 调用 MyAwaited来实现。
  2. 如果 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;