为泛型函数特化一个类型

Specialize a type for generic function

给定这个定义:

declare function foo<T>(): { bar: T }

// <T>() => { bar: T }
type Foo = typeof foo;

如何根据类型为泛型函数提供专业化?

我想要实现的是能够做到这样的事情:

// { bar: number }
type FooResult = ReturnType<Foo<number>>;

但是 TypeScript 抱怨 Foo 本身不是通用的 - 它键入的函数是。

TypeScript 并不真正支持您需要从 ReturnType 获取的那种 higher-order 类型...它是 known design limitation。因此,您所拥有的只是各种解决方法。以下是我能想到的:

  • 手动完成。这本质上是一个 non-answer,但可能是最好的前进方式,因为它不依赖于任何奇怪的类型系统技巧:

    type FooResult<T> = { bar: T };
    type FooResultNumber = FooResult<number>; // {bar: number}
    
  • 假装实际调用 foo() 并得到它的结果。 TypeScript 不支持 arbitrary type queries,所以很遗憾 type FooResult = typeof foo<number>() 无法编译。以下代码尽可能接近:

    const __dummy = (true as false) || foo<number>();
    type FooResultNumber = typeof __dummy; // {bar: number}
    

    这会在您的运行时代码中引入一个虚拟变量。 (true as false) || expression 构造使用 type assertion 来欺骗编译器。编译器认为你在​​做 false || expression,其类型将与 expression 的类型相同。您在运行时真正做的是 true || expression,其中 short-circuits,返回 true,而无需评估 expression。这意味着 foo() 尽管在代码中,但在运行时永远不会被调用。

  • 另一种假装调用 foo() 的方法是使用虚拟 class...你永远不会实例化 class 但它让编译器推理类型:

    class __FooRunner<T> {
      result = foo<T>();
    }
    type FooResult<T> = __FooRunner<T>["result"];
    type FooResultNumber = FooResult<number>; // {bar: number}
    

    同样,这会在您的运行时代码中放入一些垃圾,根据您的用例,这可能会或可能不会被接受。

好的,希望对你有帮助;祝你好运!

Link to code