-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Type of reverse mappings of numeric enums is a string
instead of keyof typeof Enum
#38806
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I can certainly agree that enum reverse mappings should have type |
I've been trying to make something like this work, but I am blocked by the same (or similar) issue. Would be really useful to not have the type loosened. enum Allowed {
A = 'a',
B = 'b',
C = 'c',
}
const values: { [key in Allowed]: boolean } = { a: true, b: false, c: true }
const filteredValues = Object.keys(values).filter((value) => values[value]) Expected behaviour: Actual behaviour: Playground link: Here |
I think enumerations are challenging to use well. For example, number enumerations contain reverse mappings: enum Enum {
one = 1,
two = 2,
}
console.log(Object.values(Enum)) // Prints ["one", "two", 1, 2] However, the typing doesn't reflect that: type EnumKey = keyof typeof Enum // "one" | "two" but not the reverse mapping.
type EnumVal = typeof Enum[EnumKey]
const foo: EnumVal = 1234 // Invalid unchecked.
const bar: EnumKey = 'one' // Valid and allowed.
const baz: EnumKey = 1 // Valid and forbidden. The problem worsens with declaration merging: enum Color {
Red,
Green,
Blue
}
namespace Color {
export function size(): number {
return Object.keys(Color).length
}
}
console.log(Color.size()) // Prints 7 not 6. Plain objects are less idiomatic and succinct but they behave as expected and a reverse mapping is optional and explicit: const Enum = <const>{
one: 1,
two: 2,
1: 'one',
2: 'two'
}
type Enum = typeof Enum[keyof typeof Enum]
console.log(Object.values(Enum)) // Prints ["one", "two", 1, 2].
type EnumKey = keyof typeof Enum // 1 | 2 | "one" | "two"
type EnumVal = typeof Enum[EnumKey] // 1 | 2 | "one" | "two"
const foo: EnumVal = 1234 // Invalid and forbidden.
const bar: EnumKey = 'one' // Valid and allowed.
const baz: EnumKey = 1 // Valid and allowed. |
I would like to see this feature as well |
The problem persist, if I have a string variable and get an enum with reverse mapping the inferred type is still string, enclosing it in a |
Found a workaround to the problem. I mention it in #50933. |
TypeScript Version: 4.0.0-dev.20200526
Search Terms:
enum
numeric enum
reverse enum
Code
Expected behavior:
When a numeric enum is indexed by itself the value should be of type
keyof typeof Enum
:No error on line (1).
Error
Property '0' does not exist on type 'typeof Enum'
on line (2).Actual behavior:
When a numeric enum is indexed by a number (including itself) the value is of type
string
:Error
Type 'string' is not assignable to type '"one" | "two"'
on line (1).No error on line (2).
Playground Link: Provided
Related Issues:
The text was updated successfully, but these errors were encountered: