Comment

Comment by shadowofneptune

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.

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton