I have a function like this in Typescript:
function combine<A, B>(p1: Parser<A>, p2: Parser<B>): Parser<A | B> { … }
Is it possible to type it for variable number of type variables (A, B, C, …) and correctly set the result type to Parser<A | B | C | …>
? I know I can do this by writing the type signatures by hand for different 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> { … }
Is that the only option?
PS. I was looking at this similar question, but the types are a bit above my head and I don’t know whether it’s the same case or not (the “endless union type” looks like an extra requirement here).
CodePudding user response:
Here's how you you can infer the result type based on the arguments. Probably that's what you're trying to achieve
function combine<T extends string>(...ps: Parser<T>[]): typeof ps extends Array<infer R> ? R : never {
throw new Error('not implemented')
}
CodePudding user response:
It is possible to implement it with array of generic types instead of unions. You can do in few ways:
Create a type and has abbility to do many arrow function implementation
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>
Create a single standart function
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>