top | item 32570299

(no title)

cuddlecake | 3 years ago

Do you have an example for what you want to do, with an object before and after mapping? I don't understand what you mean by "functionally map over a typed object by key"

discuss

order

shadowofneptune|3 years 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.

gnud|3 years ago

You can approximate something by defining the valid TokenTable keys as an enum, and using a mapped type for the actual TokenTable type.

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...

lozenge|3 years ago

Can you define a const array with type Array<TokenId> and use it every time you want to loop through these keys?

ryanmcbride|3 years ago

I can't really think of like, a practical use case but here's a jsFiddle of what I mean.

https://jsfiddle.net/knvztxq7/ ^ that code will work, it outputs the key names to the console

https://jsfiddle.net/knvztxq7/1/ ^ that code... is also working even though I swear it hasn't worked for me before so now I think I'm actually just losing my mind.

Yeah wow I can't reproduce my error now... I'll come back here if I figure out what I did.