Hacker News new | past | comments | ask | show | jobs | submit login

And that's one of the features of typescript that really sucks. String union types work so much better.



Why does typescript enum really suck?


There’s a ton written about this if you search for “typescript enums.”

I just finished removing them from a major project. Here’s a few of my personal notes:

1. They don’t play well with duck typing. (Eg. show me a subset of an enum)

2. They require an import every time you want to utilize them.

3. They are pretty wordy compared to union strings.

4. Their string value version encourages misuse as a key-value pair.

5. Unless you use the string value version, they suck to debug because logs just show 0,1,2,3.


Another one: they conflate Type and (Locator) Instance in a unique way that just about nothing else in TS does. Those are two very different things with the same name with Typescript's (antiquated) enums.

There are too many ways to accidentally import/redeclare/rescope the Type of an enum so that TS "knows" the Type, but because that type (generally) has the same "name" as the most likely (Locator) Instance it assumes the same access applies leaving runtime errors behind when that Instance isn't actually imported/available. Typescript has no easy way to tell the difference between access to the Type isn't access to the (Locator) Instance (nor vice versa). Reasoning about those runtime errors or preventing them is additionally tough for people too because of the same "name" problem for two different things.

This is something that's painfully hard to avoid in cases where you are trying to encapsulate an API's Types separate from its imports/exports because they might be introduced or manipulated at runtime (plugins, sandboxes, proxies, etc). Unfortunately, this is also too easy to accidentally do even when you aren't intentionally doing something complicated like that (trying to generate automated .d.ts files in a bundling toolchain, for example, when APIs are in the boundary space between unintentional public API and internal tree-shaking or optimized symbol renaming).


Thanks for putting into words why they just "feel" so wrong.


Let's turn it around, union types are so much easier to use and so much more powerful. Enums have only a small subset of the features, are not compatible to JavaScript code and are hard to understand (read the docs about type script enums and you will see).


Typescript enums emit a really weird object at runtime

enum CheckboxState { On; ParentOn; Off; }

Becomes

{ [0]: “On”, “On”: 0, [1]: “ParentOn”, “ParentOn”: 1, [2]: “Off”, “Off”: 2 }

So things like Object.keys give bizarre results. It’s done this way so you can use the name or the value as an index.


To be clear, this kind of structure is only emitted for numeric enums. String enums with explicitly declared static values are roughly equivalent to the equivalent Record<string, string> (runtime) and a corresponding type T[keyof T] (type check time).

IME, most of the complaints about enums apply only to numeric ones.

The major exception to that AFAIK is the fact that enum members of any type are treated as nominally typed (as in A.Foo is not assignable to B.Foo even if they resolve to the same static value). I am among the minority who consider this a good thing, but I recognize that it violates expectations and so I understand why my position isn’t widely shared.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: