0

I'm converting one of my JavaScript apps to TypeScript and I've got a problem: I've got a numeric enum, AnswerKeys and a key, "C". I'd like to get the member's value, "2", so I tried using AnswerKeys[key].

enum AnswerKeys {
  'A' = 0,
  'B',
  'C',
}
let key = 'C'
let answer = AnswerKeys[key]
// it should log 2
console.log(answer)

It would work but I receive the following TypeScript error:

Element implicitly has an 'any' type because index expression is not of type 'number'.

It seems it has a problem with key not being a number. Other answers suggested adding as any assertion or just adding "suppressImplicitAnyIndexErrors": true to the config file, and while these do suppress the error, it's not what I want.

The following works but accepts any key and I only want to accept strings:

let answer = AnswerKeys[key as any]

I also tried keyOf AnswerKeys but it results in an extra error:

enum AnswerKeys {
  'A' = 0,
  'B',
  'C',
}
let key: keyof AnswerKeys = 'C'
let answer = AnswerKeys[key]
console.log(answer)

Type '"C"' is not assignable to type '"toString" | "toFixed" | "toExponential" | "toPrecision" | "valueOf" | "toLocaleString"'.(2322)

Is there any way to annotate it correctly?

7
  • 1
    Do you need key to change? If not, you can write const key = "C" and it works. If you're looking for an annotation, you could write keyof typeof AnswerKeys and not keyof AnswerKeys (which is different), and that works too. Which one are you looking for? I'm happy to write up either version as an answer. Commented Jul 31, 2022 at 0:50
  • @jcalz Thanks, const key does work, but key is actually a parameter, it's not in the question because I tried to simplify it. It started as function func(key: string) {...} and I received the error mentioned above. It seems function func(key: keyof typeof AnswerKeys) { is what I'm looking for. Thank you! Commented Jul 31, 2022 at 1:05
  • All right I guess there's already an answer that says that. Commented Jul 31, 2022 at 1:08
  • 1
    @jcalz Any idea why (alternatively) typeof AnswerKeys[AnswerKeys] doesn't work? Or, in other words, why does TS implement reverse mapping for numeric enums but hide the related type information? Commented Jul 31, 2022 at 1:33
  • 2
    It's an open issue, see github.com/microsoft/TypeScript/issues/38806 Commented Jul 31, 2022 at 3:09

2 Answers 2

2

To get a union of all of the enum values, you can use keyof typeof Enum. This is because keyof Enum gives you the keys of the object Enum (as AnswerKeys is technically just an object/value), whereas you want the keys of the type Enum.

Using your example, the following runs with no errors:

enum AnswerKeys {
  'A' = 0,
  'B',
  'C',
}
let key: keyof typeof AnswerKeys = 'C'
let answer = AnswerKeys[key]
console.log(answer)
Sign up to request clarification or add additional context in comments.

Comments

0

Use any of the following methods:

1. Modify tsconfig.json
Add/uncomment "suppressImplicitAnyIndexErrors": true in tsconfig.json.
In newer versions of Typescript, it is called noImplicitAny.
Documentation can be found here.

2. key as keyof typeof AnswerKeys

let key = 'C'
let answer = AnswerKeys[key as keyof typeof AnswerKeys]

3. Disable linting for the line using @ts-ignore

let key = 'C'
// @ts-ignore
let answer = AnswerKeys[key]

4. Set key to type any

let key: any = 'C'
let answer = AnswerKeys[key]

Sources: https://stackoverflow.com/a/40997325/ & https://stackoverflow.com/a/66117678/

1 Comment

Thanks for your answer. I definitely don't want to use #1, #3, and #4 as I mentioned in my question. My problem with #2 is that it still accepts anything because as keyof typeof AnswerKeys is just a way to tell the compiler not to give you an error message.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.