Typescript中泛型参数的可变数量



我在Typescript中有一个这样的函数:

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

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

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> { … }

这是唯一的选择吗?

p。我正在看这个类似的问题,但是类型有点超出我的头脑,我不知道它是否是相同的情况("无尽的联合类型"看起来像一个额外的要求)。

如何根据参数推断结果类型。也许这就是你想要达到的效果

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

TS操场


编辑:

看了你的评论后,我意识到你可能想这样定义函数:

// 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

例子

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

  • 创建一个类型,并能够做许多箭头函数实现

    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>
    

最新更新