You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An enum is indexed with strings not numeric things:
const enum foo {
[x: string]: number
NaN = 1, // error: An enum member can not have a numeric name
Infinity = 2 // error: An enum member can not have a numeric name
}
constenumfoo{const,// validlet,// validvar,// validtypeof,// valid'Hello',// valid'1',// error: An enum member can not have a numeric name'NaN',// error: An enum member can not have a numeric name'Infinity'// error: An enum member can not have a numeric name}
This has nothing to do with typeof. This has to do with the fact that when indexing with a value equal to NaN (e.g. 0/0), you are actually indexing with "NaN". If we don't check to make sure an enum name is numeric, then the reverse-mapping no longer applies - in the following example, even though the expression indexed with is of type number, you'll get 10 (which is also a number) instead of "A".
enumE{A=NaN,NaN=10,}E[0/0];
Basically what we look for is whether the abstract operation ToNumber and then ToString matches the text of the enum name. See the explicit logic. See the comment that precedes it.
Whether or not it matters for const enums is arguable. Considering you can still have a reverse mapping with --preserveConstEnums, and that it's undesirable to have too many semantic differences between enums and const enums, I'm inclined to say that this is by design unless there's a sufficiently useful use case.
We disallow NaN and Infinity because we consider them to be numeric names (because (+'NaN').toString() === 'NaN'); i.e. it's the same reason you can't write enum X { '0': 1 }.
We could reasonably remove that restriction for identifier-like things because it's very unlikely you would actually have an enum member whose value was one of those non-real numbers.
We could reasonably remove that restriction for identifier-like things because it's very unlikely you would actually have an enum member whose value was one of those non-real numbers.
If you mean for all enums, I don't see why, since we've already settled on a reasonably consistent semantics.
If you mean for const enums, I feel like that would introduce more inconsistencies between the two which is undesirable.
Activity
kitsonk commentedon Jun 19, 2015
Well, enums can't have numeric names and
NaN
andInfinity
are actually numeric symbols.typeof NaN === 'number'
andtypeof Infinity === 'number'
.jbondc commentedon Jun 19, 2015
typeof "NaN" === "string" ?
jbondc commentedon Jun 19, 2015
An enum is indexed with strings not numeric things:
kitsonk commentedon Jun 19, 2015
Hmmm interesting:
DanielRosenwasser commentedon Jun 19, 2015
This has nothing to do with
typeof
. This has to do with the fact that when indexing with a value equal toNaN
(e.g.0/0
), you are actually indexing with"NaN"
. If we don't check to make sure an enum name is numeric, then the reverse-mapping no longer applies - in the following example, even though the expression indexed with is of typenumber
, you'll get10
(which is also anumber
) instead of"A"
.Basically what we look for is whether the abstract operation
ToNumber
and thenToString
matches the text of the enum name. See the explicit logic. See the comment that precedes it.Whether or not it matters for
const enum
s is arguable. Considering you can still have a reverse mapping with--preserveConstEnums
, and that it's undesirable to have too many semantic differences between enums and const enums, I'm inclined to say that this is by design unless there's a sufficiently useful use case.jbondc commentedon Jun 19, 2015
@DanielRosenwasser But NaN can't be assigned to a const enum
jbondc commentedon Jun 19, 2015
It also isn't a valid value for ambient/declared enums:
jbondc commentedon Jun 19, 2015
I was writing this code:
DanielRosenwasser commentedon Jun 19, 2015
That is a decent use case, but I'd still rather not have const enum rules deviate too much from enum rules. Perhaps others can weigh in.
@vladima and @mhegazy might have more insight as to why
NaN
and +/-Infinity
can are not valid RHSs in enum members.I don't believe it should be; declaring an enum implies that there exists a variable with the same mapping semantics at runtime.
RyanCavanaugh commentedon Jun 19, 2015
We disallow
NaN
andInfinity
because we consider them to be numeric names (because(+'NaN').toString() === 'NaN'
); i.e. it's the same reason you can't writeenum X { '0': 1 }
.We could reasonably remove that restriction for identifier-like things because it's very unlikely you would actually have an enum member whose value was one of those non-real numbers.
DanielRosenwasser commentedon Jun 19, 2015
If you mean for all enums, I don't see why, since we've already settled on a reasonably consistent semantics.
If you mean for const enums, I feel like that would introduce more inconsistencies between the two which is undesirable.
jbondc commentedon Aug 21, 2015
It could be as simple as disabling NaN or Infinity in the reverse-mapping, don't think there's any use case there.
Emits
What I find more inconsistent is this:

I've talked before about changing the semantics for the reverse mapping which I'd love to see.