如何推断泛型函数的返回类型

Posted

技术标签:

【中文标题】如何推断泛型函数的返回类型【英文标题】:How to infer return type of a generic function 【发布时间】:2020-03-23 03:20:17 【问题描述】:

我有一个总是返回类型的函数,尽管它可以更改并手动定义它会有些工作且不可扩展,所以我试图通过使用 typescript 的 infer 关键字来实现这一点

一开始我看到this reddit post 使用

type Foo<T> = T extends  a: infer U, b: infer U  ? U : never;
type T10 = Foo< a: string, b: string >;  // string
type T11 = Foo< a: string, b: number >;  // string | number

问题是,我的类型是泛型函数

这是一个最小的例子,

const fnFromLib = <T>(a: string, b: Record<string, string>) => 
  return function barFn(c: T) 
    return 
      c,
      b: b[a],
    ;
  ;
;
const foo = <T>(a: Record<string, string>) => 
  return 
    bar: fnFromLib<T>('foo', a),
  ;
;
type returnTypeInferer<T> = T extends (a: Record<string, string>) => infer U ? U : never;
type fooType = typeof foo;
type fooReturnType = returnTypeInferer<fooType>;

没有错误,但是,由于没有传递泛型类型,fooReturnType 将被推断为

type fooReturnType = 
    bar: (c: unknown) => 
        c: unknown;
        b: string;
    ;

注意到 fnFromLib 中的 T 不是从参数推断出来的,应该在函数调用中传递

type returnTypeInferer<T> = T extends (a: Record<string, string>) => infer U ? U : never;
type fooType<T> = typeof foo<T>; // ------   parsing error: ';' expected ---------
type fooReturnType<T> = returnTypeInferer<fooType<T>>;

有什么方法可以实现我想要的吗?

谢谢

【问题讨论】:

在 TypeScript 中没有 generic values 之类的东西,我认为您将不得不使用解决方法。 【参考方案1】:

通过将函数包装到泛型类中来设法做到这一点

class GnClass<T> 
  foo = (a: Record<string, string>) => 
    return 
      bar: fnFromLib<T>('foo', a),
    ;
  ;

type returnTypeInferer<T> = T extends (a: Record<string, string>) => infer U ? U : never;
type fooType<T> = GnClass<T>['foo'];
type fooReturnType<T> = returnTypeInferer<fooType<T>>;

但我想坚持使用函数式编程,我不会将此标记为已接受的答案,我会暂时使用它,因为我目前没有其他选择,并且会喜欢另一种方法。

【讨论】:

我认为这非常聪明,并且可能是您可以将泛型类型参数从函数中移出的少数几种方法之一(或者可能是唯一的方法),而无需更广泛地支持 @987654321 @。另请注意,TypeScript 提供 ReturnType&lt;T&gt; 作为实用程序类型。 感谢实用程序类型提示 :) 也许这是唯一的方法,因为我是从已实现的泛型函数中推断出一个类型,所以它必须以某种方式存在,如果可以获取类型typeof foo&lt;T&gt; 的功能会很棒,但它不是......

以上是关于如何推断泛型函数的返回类型的主要内容,如果未能解决你的问题,请参考以下文章

在 TypeScript 中推断泛型函数类型

如何使通用可变参数函数中先前声明的函数的返回类型成功进行上下文推断?

TypeScript 中泛型类型的子类型推断

从函数回调推断泛型类型参数

模板与泛型编程——模板实参推断

如何在柯里化函数中推断泛型?