在打字稿中解压缩的递归版本<T>?



引用中的Unpackedhttps://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html.

type Unpacked<T> =
T extends (infer U)[] ? U :
T extends (...args: any[]) => infer U ? U :
T extends Promise<infer U> ? U :
T;

有递归版本吗?我已经尝试过了,我得到了循环引用本身的错误。

type Unpacked<T> =
T extends (infer U)[] ? Unpacked<U> :
T extends (...args: any[]) => infer U ? Unpacked<U> :
T extends Promise<infer U> ? Unpacked<U> :
T;

由于循环引用,上述代码失败。

递归版本将做到这一点:

Unpacked<Array<Promise<number[]>>> === number;

当我们不知道它需要多深才能打开时,它很有用。

不幸的是,对于您的定义,条件类型不允许递归地引用自己,除非在特定情况下。从上面链接的拉取请求的描述中引入了以下功能:

与并集和交集类型类似,条件类型不允许递归引用自身(但是,允许通过接口类型或对象文字类型进行间接引用,如上面的DeepReadonly<T>示例所示(。例如,以下是一个错误:

type ElementType<T> = T extends any[] ? ElementType<T[number]> : T; // Error

的时候,人们设法欺骗编译器允许这样的递归类型,但也有同样的情况,有人可能会写一些东西使编译器崩溃。这是一个正式的坏主意,所以我不会试图告诉你如何做到这一点。

我也很想看到一个解决方案,但现在还没有(从TS3.0开始(。


所以,解决办法。最简单的解决方法是计算出您可能需要的实际最大深度,然后编写相应的代码。这里有一种方法:

type _U<T> =
T extends (infer U)[] ? U :
T extends (...args: any[]) => infer U ? U :
T extends Promise<infer U> ? U :
T;
// up to 8 levels deep
type Unpacked<T> = _U<_U<_U<_U<_U<_U<_U<_U<T>>>>>>>>

您可以验证这是否适用于您的示例:

type JustNumber = Unpacked<Array<Promise<number[]>>>; // number

它并不完美,但它可能是目前最好的。希望能有所帮助。祝你好运

最新更新