I'm trying to write some parsers in Typescript. My parsers are all instances of a base class, Parser
, parametrized by types, A
and S
, representing the result of a parse and the parser state.
class Parser<A, S> {
parse: (state: S) => Response<A, S>
constructor(parse: (state: S) => Response<A, S>) {
this.parse = parse
// various combinator methods...
}
In several cases of interest to me, I'd like the state S
to be adapted to parsing strings, and, also, to carrying some user-definable payload of type U
. Thus, the S
of interest might implement:
interface SS<U> {
str: string;
user: U
}
Then I'd like to construct the most basic parser I can think of: char
. It consumes and returns the first character in the string being parsed, if there is one, or fails if there isn't. Thus, I'd like
char: Parser<string, SS<U>>
for any U
.
But, alas, Typescript doesn't allow values involving generics, just functions, classes, etc. ["Variables can't have free generics", as Titian nicely puts it in the comments below.] phAre there any standard patterns to circumvent this limitation? The only "solutions" I can think of are:
Make
char
into a function:function char<U>(): P<U> {...; return realChar}
. I don't find this workaround appealing because there's a runtime cost every time I runchar()
.Wrap all my parsers that depend on
U
in a function:function parsers<U>() { let char: Parser<string, SS<U>> = ... let letter: Parser<string, SS<U>> = ... let digit: Parser<string, SS<U>> = ... // other parsers return {char, digit, letter, ...} }
Then I could instantiate them all by running
parsers()
when I use them and have a concreteU
at hand.
Are there any other approaches that are more elegant or that incur minimal runtime overhead, or an established pattern? [Anyone know if anything like "values of generic type" (is there better terminology for this?) on the Typescript roadmap?]