柯里化函数的返回类型

ReturnType of curried function

在函数 return 中使用 ReturnType<T>,如您所料,return 类型。

type F = () => string
//ReturnType<F> === string

此外,如您所料,当使用柯里化函数时,return 类型是

type FF = () => () => string
//ReturnType<FF> === () => string

有没有办法创建 return 最终 return 的通用类型?即.E

type FF = () => () => string
//FinalReturnType<FF> === string

这目前有效(TS 3.7),但 TS 团队并没有故意允许它,也没有决定支持它。它可能会在未来的版本中中断。

type FinalReturnType<T> = {
  0: T,
  1: T extends (...args: any) => infer R ? FinalReturnType<R> : T,
}[T extends (...args: any) => infer _ ? 1 : 0];

它必须如此奇怪和丑陋,因为目前有一个限制说一个类型只能在嵌套在另一个结构类型(在这种情况下,一个有两个键的对象)中时调用自己,但是我们立即拉属性 我们需要的元组。

理想的外观:

如果语言支持这种机制,我认为它会很简单:

type FinalReturnType<T> = T extends (...args: any) => infer R
                              ? FinalReturnType<R> 
                              : T;

换句话说,使用递归定义。如果 T 是一个函数,它调用自己传递函数的 return 类型。如果不是一个函数,它 return 就是 T 本身。例如:

FinalReturnType<string> // -> string

这样就终止了递归:当您展开 return 函数的所有函数层时,您最终会得到一个非函数。

不幸的是,这是不可能的,会产生错误:

Type alias 'FinalReturnType' circularly references itself.

有一个 change to enable recursive type references 但它没有启用此方案。

an open discussion of more general support for recursion.

目前的情况是,如果您在自调用周围添加 [] 使其成为一个元组,您只能编译我的答案:

type FinalReturnType<T> = T extends (...args: any) => infer R
                                ? [FinalReturnType<R>] 
    : T;

type t1 = FinalReturnType<string>;  // -> string

type F = () => string
type t2 = FinalReturnType<F>;       // -> [string]

type FF = () => () => string
type t3 = FinalReturnType<FF>;      // -> [[string]]

如您所见,这将结果重新包装在嵌套元组的层中,您又回到了同样的问题,因为您也无法打开它们。

目前,您目前可以使用在具有两个属性的对象中包装的技巧,然后通过索引正确的属性立即解包,如本答案顶部所述。但这是偶然启用的,TS 团队不确定他们是否要 support/encourage 这个。