【问题标题】:TypeScript: How to obtain return type of the instance of a generic function that has a specified parameter tuple type?TypeScript:如何获取具有指定参数元组类型的泛型函数实例的返回类型?
【发布时间】:2022-12-21 12:47:24
【问题描述】:

假设我有通用功能

function example<T>(a: T, b: number): SomeType<T> {
   // code goes here
}

但是,为了争论起见,我不知道 example 是否在第一个或第二个参数的类型上是泛型的,或者它可能是具有两个类型参数的泛型。我的目标是确定带有参数元组 [string, number]example 实例化的返回类型。 (所以最好有类似InstantiatedReturnType&lt;F, ParamTuple&gt;的东西,这样在这种情况下InstantiatedReturnType&lt;typeof example, [string, number]&gt;就是SomeType&lt;string&gt;。)我已经验证typeof example确实扩展了类型(...args: [string, number]) =&gt; any,但我无法找到一种方法来提取具有此参数元组类型的实例化的返回类型。特别是,如果我采用函数类型 typeof Example(...args: [string, number]) =&gt; any 的交集,它的 ReturnType&lt; &gt; 等于 anyunknown ,具体取决于我在交集中列出两种类型的顺序。另外,因为函数类型在它们的参数中是逆变的,所以我尝试使用这两种类型的并集 ReturnType&lt; &gt;,但这也没有帮助。欢迎任何建议或指导。

(我不知道模板结构的观点是,我没有能够说出 ReturnType&lt;typeof example&lt;string&gt;&gt; 的信息,因为与参数 [string, number] 匹配的实例化实际上可能是 example&lt;number&gt;,因为 example 实际上是通用的第二个参数类型,并在第一个参数中显式为字符串。用例是我得到一个对象,其值是我可能想调用的替代函数,其中一些可能是通用的,我正在选择一个基于匹配我拥有的参数元组类型的调用。这部分工作——我可以成功地提取键(作为一个具体类型,只有一个字符串居民),其值是一个(可能是通用的)函数,可在元组类型上调用我得到的参数的一部分,但我还需要表达调用将产生的返回类型,我似乎无法管理它。)

更新:this playground 中有一个我试图完成的精简示例。它显示了选择正确的密钥,以及一次获取“匹配实例化”的返回类型的不成功尝试。

【问题讨论】:

  • 您无法执行纯类型级别的操作来获得此信息;该语言缺乏真正的高级类型,因此无法表达这一点。值级别中有 some support for higher order function inference,但如果您的用例没有 minimal reproducible example,则很难知道它是否有效。你能提供一个吗?
  • @jcalz 感谢您的观看;发布了一个示例,我希望它能更清楚地说明我正在尝试做什么。
  • 我想不出任何可用的方法来做到这一点,抱歉。没有higher kinded types我认为这是不可能的。您想要一个说“不,这不能完成”的答案以及来源吗?或者您是否在寻找(糟糕的)解决方法,涉及手动执行编译器无法自动执行的操作?
  • 好吧,如果不是太麻烦的话,我当然不介意看到最不可怕的解决方法......但是我没有在玩具示例中添加的一个功能是该对象也可能具有显式功能,可以想象这可能是比赛。我会更新这个例子。
  • This 是我能想到的最不糟糕的解决方法,您可以在其中手动拼出从输入到输出的类型逻辑。您是否希望将其写在答案中,或者它的用处不足以值得我努力解释吗?

标签: typescript generics return-type


【解决方案1】:

不,不幸的是,从 TS4.9 开始,这在 TypeScript 中是不可能的。无法在类型级别表达对泛型的操作;没有“通用泛型”或高等类型,按照microsoft/TypeScript#1213 的长期开放功能请求中的要求。

因此,虽然编译器可以在给定特定输入的情况下找出通用函数的输出类型如果你真的调用函数在表达式级别(如果 example("abc", 123) 出现在您的代码中),虽然甚至还有一些 support for higher order generic functions(例如,如果 call 的类型为 &lt;A extends any[], R&gt;(f: (...args: A)=&gt;R, ...args: A)=&gt;R,您可以获得 call(example, "abc", 123) 以产生 string),但有没有纯类型级别的等价物。在某些时候,您必须实际调用具有实际输入的函数(或说服编译器您正在这样做)以查看输出类型。

microsoft/TypeScript#17961 有一个 pull request,它可以启用类型级函数应用程序,因此,有了 type Example = typeof example,你就可以编写 type RetType = Example(string, number)。但这从未合并到该语言中,并且基本上与 microsoft/TypeScript#6606 的大部分内容一起被放弃了,这是一个能够查询所有表达式的类型而实际上不需要将这些表达式发送到 JavaScript 的一般请求。

目前在 microsoft/TypeScript#40179 有一个开放的功能请求,用于此功能。它被列为等待更多反馈,这意味着他们在考虑将其作为语言的一部分之前需要听取更多的社区参与。如果它对您很重要,您可以给它一个 ?,并描述您的用例及其引人注目的原因。但我没有看到任何迹象表明它会很快发生,即使它有更多的参与度。

这一切都意味着编译器不能为你做这件事,你需要要么完全放弃,要么重构你的代码,这样你就可以手动进行类型处理(并且可能是你可以让编译器查看你做对了)。但是这样的解决方法并不令人愉快,并且不直接在这个问题的范围内。

[编辑:更正了上面的问题编号。]

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2021-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
  • 2016-04-05
相关资源
最近更新 更多