8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何从泛型函数类型获取返回类型?

Gladitor 2月前

21 0

我有一个接受解析器函数的函数 api。解析器是通用的,例如,返回与输入相同的类型(并非总是这样,只是为了简化)。我...

我有一个函数 api ,它接受一个解析器函数。解析器是通用的,例如,返回与输入相同的类型(并非总是这样,只是为了简化)。

api 函数中我知道将传递给解析器输入什么类型( string 为了简单起见,实际上是通过模板化传递给 api 函数的其他参数来确定的)。

如何 api 根据 parse 为模板指定参数的返回类型来设置函数的返回类型?

// in the lib
type Parse = <T>(val: T) => any

let api = <P extends Parse>(
  parse: P,
) =>
  parse("xxx") as ???


// somewhere
let identity = <T>(val: T): T => val
let res = api(identity)

我尝试过的:

let api = <P extends Parse>(
  parse: P,
) =>
  parse("xxx") as ReturnType<P<string>> // error "Type P is not generic"
                                        // we can't specify type arguments of generic function type
let api = <P extends Parse>(
  parse: P,
) =>
  parse("xxx") as P extends (val: string) => infer O ? O : never // unknown
let api = <P extends Parse>(
  parse: P,
) =>
  parse("xxx") as ReturnType<typeof parse<string>> // any, instantiation expression don't work either

我想指出的是,我无法访问该 parse 函数的实现。它可以是任何适合该 Parse 类型的函数(如果需要,我可以更改它)。

帖子版权声明 1、本帖标题:如何从泛型函数类型获取返回类型?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Gladitor在本站《typescript》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我不知道该说什么才能避免重复。如果输出类型取决于输入类型,这是不可能的,这就是 ms/TS#40179 的要点。当然,如果返回类型不依赖于泛型类型参数,它会起作用,但这不是你要问的。你只是想让我重申我的评论,然后再告诉我它是否完全解决了你的问题?还是说我错过了你的问题的一些重要方面,这使得它与 ms/TS#40719 不同?

  • 这超出了 TypeScript 的能力。


    无法提出这样的问题:“对于给定的泛型函数类型 类型 F = <T>(⋯)=>⋯ 类型参数实例化类型参数, T 函数的类型将是什么 U ?”如果您有一个实际的泛型函数 表达式 f 而不仅仅是 type F ,则可以使用 instantiation expression 实例化表达式 f<U> 。但是无法纯粹在类型级别执行此操作。请参阅 microsoft/TypeScript#47607 上的此评论 :

    [I]实例化表达式目前在类型领域没有等效项。我们不能仅仅采用 T<X> 类型实例化语法,因为它已经意味着其他东西(即,将类型参数应用于泛型类型 T )。

    也许有一天会有这样一种类型级别的解决方案,使用一些特殊的语法,例如 F«U» 或类似的东西。但目前还不可能。


    但情况甚至更糟。你有一个 generic 限制 P 为的 泛型 类型参数 Parse 。但这并不意味着这 P 是一个泛型函数类型。例如,你可以调用

    api((x: unknown) => 123); // okay
    

    TypeScript 中没有办法抽象地谈论“调用签名只有一个类型参数的泛型函数类型”。这将需要类似 更高类型的类型 中所述的 microsoft/TypeScript#1213 。因此, P 不会接受类型参数,因此即使使用假设的 F«U» 语法, P«string» 也不会被允许。或者也许它被允许,但对非泛型函数不做任何事情?

    即使如此,情况也会变得更糟,因为你只是假设类型参数是第一个函数参数的类型。否则 P«string» 可能与调用无关 parse("xxx") 。想象一下有人这样调用:

    const g = <T,>(x: unknown, y?: T) => y;
    // const g: <T>(x: unknown, y?: T | undefined) => T | undefined
    api(g)
    

    你不能指望 g<string> 与返回类型有任何关系 parse("xxx") .


    实际上,您的代码示例看起来根本不像您想询问泛型。相反,您想问“给定一个 f 类型的 F 一个类型的 u 有效参数 U ,的类型是什么 f(u) ?”这将需要所谓的 调用类型 ,TypeScript 也不支持,因此这仍然超出了 TypeScript 的能力。在 microsoft/TypeScript#40179 。也许将来会有一些语法来 F(U) 表示这一点。在这样一个假设的世界中,您的示例将是

    // NOT VALID TS, DON'T TRY THIS:
    let api = <F extends (x: string) => any>(parse: F): F(string) => 
      parse("xxx");
    

    然后,当你调用时, api(identity) string unknown 像预期的那样得到结果,而不是 。而且它不需要 输入是一个通用函数,只要它可以像调用一样调用 (x: string) => any 。据推测这也可以 overloads {(x: string): number; (x: number): string} .

    但同样,它不是语言的一部分。目前你能得到的最接近的是 the ReturnType utility type ,它完全无法解析泛型类型参数或重载调用签名。


    总之,这是不可能的。

    游乐场链接到代码

返回
作者最近主题: