我在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>