enum Direction {
Down = -1,
Up = 1
}
let i = 1;
for (const direction of Object.values(Direction)) {
console.log('iteration ' + i++);
console.log(direction);
}
iteration 1
Up
iteration 2
-1
iteration 3
Down
iteration 4
1
I was expecting:
iteration 1
-1
iteration 2
1
Generated js:
var Direction;
(function (Direction) {
Direction[Direction["Down"] = -1] = "Down";
Direction[Direction["Up"] = 1] = "Up";
})(Direction || (Direction = {}));
var i = 1;
for (var _i = 0, _a = Object.values(Direction); _i < _a.length; _i++) {
var direction = _a[_i];
console.log('iteration ' + i++);
console.log(direction);
}
I'm sure there's a workaround but I really just want to know what causes this to go against every single expectation I had
Just take a look at the generated JavaScript output:
var Direction;
(function (Direction) {
Direction[Direction["Down"] = -1] = "Down";
Direction[Direction["Up"] = 1] = "Up";
})(Direction || (Direction = {}));
We're only going to focus on the two lines inside:
Direction[Direction["Down"] = -1] = "Down";
Direction[Direction["Up"] = 1] = "Up";
Assignments are really just expressions that "return" the new value assigned to the target. So, after we assign -1
to Down and 1
to Up, we assign "Down"
to -1
and "Up"
to 1
, which gives us a reverse mapping that allows you to look up the name of an enum member:
console.log(Direction[Direction.Down]); // "Down"
Basically, your enum looks like this at runtime:
{
"1": "Up",
"Down": -1,
"-1": "Down",
"Up": 1
}
However, this behavior is only seen in numeric enums. For example, a string enum like this will not produce a reverse mapping:
enum Direction {
Down = "down",
Up = "up",
}
As for the fix, you can check if the value is a number or not:
let i = 1;
for (const direction of Object.values(Direction)) {
if (typeof direction !== "number") continue;
console.log('iteration ' + i++);
console.log(direction);
}