[TypeScript] Type Challenges #189 - Awaited

126 阅读1分钟

题目描述

假如我们有一个 Promise 对象,这个 Promise 对象会返回一个类型。在 TS 中,我们用 Promise 中的 T 来描述这个 Promise 返回的类型。请你实现一个类型,可以获取这个类型。

例如:Promise<ExampleType>,请你返回 ExampleType 类型。

type ExampleType = Promise<string>

type Result = MyAwaited<ExampleType// string

题解

// ============= Test Cases =============
import type { EqualExpect } from './test-utils'

type X = Promise<string>
type Y = Promise<{ fieldnumber }>
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>, { fieldnumber }>>,
  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