Awaited

for typehero

just paste some code and brief description here, if wanna see the full content, please click the link above.

If we have a type which is a wrapped type like Promise, how we can get the type which is inside the wrapped type?

For example: if we have Promise <ExampleType> how to get ExampleType?

type ExampleType = Promise<string>

type Result = MyAwaited<ExampleType> // string

case

type MyAwaited<T> = any
import type { Equal, Expect } from '@type-challenges/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>

分析🙉:

从case当中可以一眼得出会是一个递归的情况;

首先最基本的情况,能用infer推到出Promise中的类型;

type MyAwaited<T> = T extends Promise<infer U> ? U : T

那么接下来处理嵌套的问题,很自然的写出这样的代码,

type MyAwaited<T> = T extends Promise<infer U> ? MyAwaited<U> : T 

但是存在的一个问题就是最后一个case它并不是一个标准的Promise,但ts库提供了一个PromiseLike

是以Interface 定义的接口类型。它需要实现thenable 特征。 简而言之只要含有then方法的对象都可以被认为是一个PromiseLike类型;与Promise相差无几。但相比之下少了个catch 和finally 的定义,比Promise定义宽松得多。如AXIOS自己封装了一个针对异步请求的AxiosPromise类型。

所以将答案修改为:

type MyAwaited<T> = T extends PromiseLike<infer U> ? MyAwaited<U> : T 

但是还需要主要到最后一个case

// @ts-expect-error
type error = MyAwaited<number>

上面的类型最终的返回结果会是一个number,然后想到对初始的泛型T做一个限制

type MyAwaited<T extends PromiseLike<any>> = T extends PromiseLike<infer U> ? MyAwaited<U> : T 

但是上面的类型会报错Type 'U' does not satisfy the constraint 'PromiseLike<any>'. 即推断的U类型不一定满足PromiseLike<any>的约束;

type MyAwaited<T extends PromiseLike<any>> = T extends PromiseLike<infer U> ? (U extends PromiseLike<any> ? MyAwaited<U> : U) : T 

考虑再嵌套一层在中间加一层判断符合 PromiseLike<any>的约束走递归,否则直接就是拿到了原始类型返回;

当然也会有ts本身支持类型的一种写法:

type MyAwaited<T extends PromiseLike<any>> = Awaited<T>

综上

学习了PromiseLike\Awaited

评论

加载中…

    ← 返回 Leetcode