|
|
|
|
|
by shadowofneptune
1396 days ago
|
|
I think I have run into a similar issue. I wrote a lexer in Typescript. It is table-based, as is the parser that runs after it. The type for the table looks something like this: type TokenTable<T> = {
plus: T,
minus: T,
bang: T,
parenOpen: T,
//etc.
};
I also have a type defined as 'type TokenID = keyof TokenTable<unknown>;' this makes it possible to check if a string is a valid key at compile-time. The innermost loop of the lexer is a for..in loop. This gives you the keys of the object. One problem: if you try to apply the TokenID type to the loop variable, you get this message: "The left-hand side of a 'for...in' statement cannot use a type annotation." Because of the design of JavaScript, TS cannot give object keys any other type but 'string', even though this type seems like a clear match.To get the typechecking back on the keys, you either need to declare the loop variable outside of the loop itself, or use type casting like this: let token = "";
let id: TokenID | undefined;
for (let key in patterns) {
const match = patterns[key as TokenID].exec(substring);
if (match && (match[0].length > token.length || key == "EOF")) {
token = match[0];
id = key as TokenID;
}
}
Neither is particularly clean. |
|
There's some boilerplate in the definition, but it's fairly clean and non-repetitive. And easy to use in the "client code".
https://www.typescriptlang.org/play?#code/KYOwrgtgBAKg9ga1AS...