引用https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html中的Unpacked
。
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;
当我们不知道它需要打开多深时,它很有用。
答案 0 :(得分:4)
很遗憾,根据您的定义,除非在特定情况下,conditional types不允许递归引用自己。在上述链接请求请求的描述中,介绍了该功能:
类似于联合和相交类型,不允许条件类型递归地引用它们自己(但是,如上面的
DeepReadonly<T>
示例所示,允许通过接口类型或对象文字类型的间接引用)。例如,以下是错误:
type ElementType<T> = T extends any[] ? ElementType<T[number]> : T; // Error
有些时候,人们已经设法愚弄了编译器以允许像这样的递归类型,但是在某些情况下,有些人可能会编写使编译器崩溃的东西。它是正式的a bad idea,因此我不会尝试告诉您如何使用该方法。
我也希望看到一个解决方案,但是现在还不存在(无论如何从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
这不是完美的,但它可能是目前为止最好的。希望能有所帮助。祝你好运!