Is there a better way to handle a mapping of type parameters in TypeScript?
export function $S(): Parser<[]>
export function $S<A>(fn: Parser<A>): Parser<[A]>
export function $S<A, B>(a: Parser<A>, b: Parser<B>): Parser<[A, B]>
export function $S<A, B, C>(a: Parser<A>, b: Parser<B>, c: Parser<C>): Parser<[A, B, C]>
export function $S<A, B, C, D>(a: Parser<A>, b: Parser<B>, c: Parser<C>, d: Parser<D>): Parser<[A, B, C, D]>
export function $S<A, B, C, D, E>(a: Parser<A>, b: Parser<B>, c: Parser<C>, d: Parser<D>, e: Parser<E>): Parser<[A, B, C, D, E]>
export function $S<A, B, C, D, E, F>(a: Parser<A>, b: Parser<B>, c: Parser<C>, d: Parser<D>, e: Parser<E>, f: Parser<F>): Parser<[A, B, C, D, E, F]>
export function $S<A, B, C, D, E, F, G>(a: Parser<A>, b: Parser<B>, c: Parser<C>, d: Parser<D>, e: Parser<E>, f: Parser<F>, g: Parser<G>): Parser<[A, B, C, D, E, F, G]>
export function $S<A, B, C, D, E, F, G, H>(a: Parser<A>, b: Parser<B>, c: Parser<C>, d: Parser<D>, e: Parser<E>, f: Parser<F>, g: Parser<G>, h: Parser<H>): Parser<[A, B, C, D, E, F, G, H]>
export function $S<A, B, C, D, E, F, G, H, I>(a: Parser<A>, b: Parser<B>, c: Parser<C>, d: Parser<D>, e: Parser<E>, f: Parser<F>, g: Parser<G>, h: Parser<H>, i: Parser<I>): Parser<[A, B, C, D, E, F, G, H, I]>
export function $S<A, B, C, D, E, F, G, H, I, J>(a: Parser<A>, b: Parser<B>, c: Parser<C>, d: Parser<D>, e: Parser<E>, f: Parser<F>, g: Parser<G>, h: Parser<H>, i: Parser<I>, j: Parser<J>): Parser<[A, B, C, D, E, F, G, H, I, J]>
export function $S(...terms: Parser<any>[]): Parser<any[]>
// Minimal definition of parser
interface ParseState {
input: string
pos: number
}
interface ParseResult<T> {
nextPos: number,
value: T,
}
interface Parser<T> {
(state: ParseState): ParseResult<T> | undefined
}
Basically I have a "sequence" function that takes any number of arguments and I'd like to know if there is a way to automatically map each type parameter into the response signature other than needing to make an overload for each number of arguments. I've seen this pattern used before but it's 2022 so I'm hoping there is a better way.
Background info that may be relevant to the question: Each Parser is a function that takes the current state (input string, current position) and returns a ParseResult if it matches at that position or undefined if it does not match. The ParseResult has a value and the new position to advance the input state to.
Parser? Especially where you show some calls to$S()so we can all verify that the suggested solution behaves as expected.Parsercould break it potentially playground