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?

Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57
  • 1
    Do you need `key` to change? If not, you can write `const key = "C"` [and it works](https://tsplay.dev/W4P3XW). If you're looking for an annotation, you could write `keyof typeof AnswerKeys` and not `keyof AnswerKeys` (which is [different](https://stackoverflow.com/a/50396312/2887218)), [and that works too](https://tsplay.dev/Na2gEm). Which one are you looking for? I'm happy to write up either version as an answer. – jcalz Jul 31 '22 at 00: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! – Zsolt Meszaros Jul 31 '22 at 01:05
  • All right I guess [there's already an answer](https://stackoverflow.com/questions/73179933/get-typescript-enum-numeric-value-by-member-name/73180003#73180003) that says that. – jcalz Jul 31 '22 at 01:08
  • 1
    @jcalz Any idea why (alternatively) [`typeof AnswerKeys[AnswerKeys]`](https://tsplay.dev/Wz53km) doesn't work? Or, in other words, why does TS implement [reverse mapping](https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings) for numeric enums but hide the related type information? – jsejcksn Jul 31 '22 at 01:33
  • 2
    It's an open issue, see https://github.com/microsoft/TypeScript/issues/38806 – jcalz Jul 31 '22 at 03:09
  • Does this answer your question? [dynamically access enum in typescript by key](https://stackoverflow.com/questions/50417254/dynamically-access-enum-in-typescript-by-key) – chitinlink Apr 24 '23 at 13:10
  • @chitinlink I don't think it's a duplicate. Which one of those do you think answers my question the same way or better than the accepted answer here? – Zsolt Meszaros Apr 24 '23 at 14:36

2 Answers2

1

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)
cyn
  • 3,509
  • 2
  • 14
  • 19
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/

Zsolt Meszaros
  • 21,961
  • 19
  • 54
  • 57
Maytha8
  • 846
  • 1
  • 8
  • 26
  • 1
    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](https://tsplay.dev/NDy4Vm) because `as keyof typeof AnswerKeys` is just a way to tell the compiler not to give you an error message. – Zsolt Meszaros Jul 31 '22 at 09:09