题目的地址
type MyAwaited<T> = any
type X = Promise<string>
type Y = Promise<{ field: number }>
type Z = Promise<Promise<string | number>>
type Z1 = Promise<Promise<Promise<string | boolean>>>
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>>,
]
// @ts-expect-error
type error = MyAwaited<number>
题目解析
第一步 : 限制传进来的值只能是 promise
type MyAwaited<T extends Promise<any>> = any
// 防止 @ts-expect-error 报错
// type error = MyAwaited<number>
第二步: 如果只是为了解除数组的第一个元素报错 赋值 string 即可
type MyAwaited<T extends Promise<any>> = string
第三步: 解决数组中第二个元素报错
使用 infer 设置一个变量 或者说是 一个未知数
type MyAwaited<T extends Promise<any>> = T extends Promise<infer X> ? X : X
// 不管 X 是什么 我们只管返回 X(参数) 也就是 string 或者 { field: number }
第四步: 解决数组元素中的第三个和第四个报错
现在数组第三第四元素中的 promise 有了嵌套结构 Promise<Promise<string | number>>
我们可以使用递归, 只要是 promise 就递归
按照上面的写法 此时的 X 应该为 Promise<string | number T >
也有可能为数组中 前两 元素中的普通类型 也就是 string 或者 { field: number }
// 所以我们应该在进行限制 总共有两种可能
// 1. 为Promise<string | number> 此步骤应该让他递归并且将 X传入进去
// 2. string 等等非promise的参数
X extends Promise<any> ? MyAwaited<X> : X
最终的代码
type MyAwaited<T extends Promise<any>> = T extends Promise<infer X>
? X extends Promise<any> ? MyAwaited<X> : X
: X // 这个X可写可不写, 因为上面已经片段完毕,不会进入到此步骤