Skip to content

Inconsistent behaviour with Object.values and enums with number values #30487

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

Closed
BennoDev opened this issue Mar 19, 2019 · 5 comments
Closed
Labels
Question An issue which isn't directly actionable in code

Comments

@BennoDev
Copy link

TypeScript Version:

Version used: 3.3.3333

I have reproduced this using typescript/@next which at the time of writing is 3.4.0-dev.20190319

Search Terms:

object.values
object.values enum
enum values

Code

enum DirectionNumber {
    Down,
    Neutral,
    Up
}

console.log(Object.values(DirectionNumber);

// output ["Down", "Neutral", "Up", 0, 1, 2]

Expected behavior:

Expecting consistent output, logging the enum values correctly.

This expected behaviour is also shown in the provided playground where I compare it with the erroneous behaviour.

Actual behavior:

When Object.values gets passed an enum with numbers as values, the resulting array contains both these numbers AND the keys. This seems unintuitive and unintended behaviour.

Playground Link:

Playground link

Related Issues:

@jcready
Copy link

jcready commented Mar 19, 2019

This is well documented and intended behavior. See documentation for reverse mappings in enums.

@BennoDev
Copy link
Author

BennoDev commented Mar 19, 2019

Ah alright, thanks, I skimmed over that part of the documentation.

I have no doubt that the generated code is intended, however to me this behaviour conflicts with what is also documented ''enums are real objects that exist at runtime".

Given the fact that enums in typecript have been around longer than Object.values() in ES the statement that 'enums are objects' has always been true, up to this point.

If the intention is for people to be able to use enums as 'just objects' in runtime, then it should function correctly with all methods on the Object constructor.

@nmain
Copy link

nmain commented Mar 19, 2019

I don't see a conflict there. In order for DirectionNumber.Down == 0 and DirectionNumber[0] == "Down" to be true, then in the transpiled js DirectionNumber has to have a shape that looks something like:

var DirectionNumber = { Down: 0, 0: "Down" };

But then, without any typescript involvement you get:

console.log(Object.values(DirectionNumber)); // ["Down", 0]

And this is exactly what you'd expect out of any plain javascript object that obeyed obj.Down == 0 && obj[0] == "Down"

@BennoDev
Copy link
Author

BennoDev commented Mar 19, 2019

I understand the logic and reasoning behind the generated code, and why they currently appear in these arrays, but I disagree that this behaviour is desirable.
The fact is that 2 very similar and valid uses of enums behave quite differently.
On top of that it doesn't seem intuitive that a method called Object.values returns an array containing both key and values (and the other way around for Object.keys), for something that is for all intents and purposes designed to behave just like a normal object/key-value pair.

It's possible to skip enumeration of these key/value pairs generated for reverse mapping using Object.defineProperty, and still have properly functional reverse-mapping through property access. Demonstration here

@RyanCavanaugh RyanCavanaugh added the Question An issue which isn't directly actionable in code label Mar 19, 2019
@RyanCavanaugh
Copy link
Member

The codegen for enums was chosen when ES3 targets (which don't have defineProperty) were still very common. Generating substantially different code between ES3 and ES5 targets is a worse inconsistency than someone's first-guess interpretation of Object.keys(E) being wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants