【问题标题】:Variable number of generic parameters in TypescriptTypescript 中可变数量的泛型参数
【发布时间】:2021-10-13 14:19:07
【问题描述】:

我在 Typescript 中有这样的功能:

function combine<A, B>(p1: Parser<A>, p2: Parser<B>): Parser<A | B> { … }

是否可以为可变数量的类型变量(A,B,C,...)键入它并将结果类型正确设置为Parser&lt;A | B | C | …&gt;?我知道我可以通过为不同的 arities 手动编写类型签名来做到这一点:

function combine<A>(p1: Parser<A>): Parser<A>;
function combine<A, B>(p1: Parser<A>, p2: Parser<B>): Parser<A | B>;
// …and so on…
function combine(...parsers: Parser<any>[]): Parser<any> { … }

这是唯一的选择吗?

附言。我在看this similar question,但是类型有点超出我的想象,我不知道它是否是相同的情况(“无限联合类型”在这里看起来像是一个额外的要求)。

【问题讨论】:

    标签: typescript generics


    【解决方案1】:

    以下是根据参数推断结果类型的方法。可能这就是你想要实现的目标

    function combine<T extends string>(...ps: Parser<T>[]): typeof ps extends Array<infer R> ? R : never {
        throw new Error('not implemented')
    }
    

    TS Playground


    编辑:

    阅读您的评论后,我意识到您可能想要这样定义函数:

    // generic extending parser Array
    function combine<T extends Parser[]>(...ps: T): typeof ps extends Array<infer R> ? R : never {
        throw new Error('not implemented')
    }
    

    这样你就可以传递一个元组作为通用参数来定义参数的类型和位置

    const result = combine3<[B, A]>(parserB, parserA)
    // typeof result is B | A
    

    或者不强制执行位置,让 ts 推断返回类型

    const result = combine(parserB, parserA, parserA, parserC)
    // typeof result is B | A | C
    

    examples

    【讨论】:

    • 谢谢,但我需要 A、B、C 类型不相关。换句话说,我需要一个类似于foo&lt;A, B, C, …&gt;(arg1: A, arg2: B, arg3: C, …): A | B | C | …的函数签名。
    • @zoul 我想我现在已经理解了这个问题,所以我更新了我的答案。希望有所帮助
    【解决方案2】:

    可以使用泛型类型数组而不是联合来实现它。您可以通过以下几种方式进行:

    • 创建一个类型并且可以做很多箭头函数的实现

      type ParserFunc<T extends any[]> = (...args: {
        [P in keyof T]: T[Parser<P>]
      }) => Parser<T[number]>
      
      const function1: ParserFunc<[string,number]> = (p1, p2) => { ... }  // => Parser<string | number>
      const function2: ParserFunc<[string,string]> = (p1, p2) => { ... }  // => Parser<string>
      const function3: ParserFunc<[string,boolean]> = (p1, p2) => { ... } // => Parser<string | boolean>
      
    • 创建单个标准函数

      function combineParser<T extends any[]>(...args: {
        [P in keyof T]: T[Parser<P>]
      }): Parser<T[number]> {
        // ...
      }
      
      combineParser(1,'2',true, null) // => Parser<number | string | boolean | null>
      

    【讨论】:

      猜你喜欢
      • 2018-08-04
      • 1970-01-01
      • 2010-12-09
      • 2019-07-09
      • 2023-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-14
      相关资源
      最近更新 更多