3 ms·
> seeing `Direction.North` is a whole lot more semantically meaningful than the string "north" in code This is subjective, so we can agree to disagree, but per
by brundolf 4y ago
> seeing `Direction.North` is a whole lot more semantically meaningful than the string "north" in code
This is subjective, so we can agree to disagree, but personally assuming I have typechecking/autocomplete I really prefer knowing exactly what I have (a string), and not hiding it behind an abstraction
And, if you ever just want the values enumerated for whatever reason, you can always do it yourself explicitly:
const Direction = {
North: 'North',
South: 'South',
East: 'East',
West: 'West'
} as const
type Direction = keyof typeof Direction
Compared with the above, the special enum syntax just creates unnecessary magic in my opinion; it even breaks TypeScript's rule of not having any runtime footprint
> More than that, refactoring tooling Just Works with enums
I just entered the following in my editor:
type MyEnum = 'A' | 'B' | 'C'
const x: MyEnum = 'A'
1. When I typed open-quote in front of `=`, it intellisensed/autocompleted on the possible strings
2. I was able to right-click 'A' in the type definition, click "Rename...", and then it updated both the type and the 'A' literal value with the new value
- zdragnar 4y agoNow try this: type MyEnum = 'a' | 'b' | 'c'; function test(val: MyEnum) { return val; } // refactors test('a'); // does not refactor const testVal = 'a'; test(testVal); The simple fact is that- as far as the type system is concerned, enums are more than simple strings, and they are useful for those differences. As for the readability, it gets a little more interesting when you are interacting with libraries or APIs outside of your control; you end up with hyphenated things, underscored, and other oddities that may not be a one-to-one match between a logical, easily readable key and the underlying value it represents.
- brundolf 4y ago> Now try this Sure- the auto-refactor won't work here, only the typecheck, and that's the desired behavior in this case because the intended use of 'a' is not necessarily known at that point in the code. Which is the point you're making I guess, though I have to say, in practice this is an unusual case that I never really see; usually if I'm creating an enum-string it's directly in a function call, typed object literal, etc. > as far as the type system is concerned, enums are more than simple strings enum MyEnum { Foo, Bar } function test(val: MyEnum) { return val; } test(MyEnum.Foo) test('Foo') I was surprised to find you were right about this; I expected the above to pass checks, but it doesn't. TypeScript actually does treat the enum as more than just its underlying value. So that's interesting- and that's the first reason I've really seen to use these But I think I still prefer plain values, for myself. There's just something that feels right and pure about using plain JSON-like JavaScript values, and then overlaying types on top of them that have no effect on their behavior and don't obscure their underlying representation. You know exactly what you've got, it's maximally duck-typeable, it's unchanged when it gets (de)serialized, it all just feels better to me
- BlargMcLarg 4y ago>though I have to say, in practice this is an unusual case that I never really see They happen once in a blue moon and when they do, you hate your life for a day. Maybe a week. Plain values also have the problem of losing context. This primarily hits those who don't know the code. That's the whole selling point of OOB and related abstractions, anyway. Both of the above happening in tandem isn't that rare and a realistic risk factor for big projects.
- brundolf 4y ago> you hate your life for a day. Maybe a week. I'm not sure why I would? TypeScript would still lead me straight to the problem via type incompatibilities; it just wouldn't perform the fix for me automatically in this one specific case
- Tistron 4y agoWhat do you mean with "does not refractor"? Do you mean it doesn't compile, because it doesn't. You need to write either const testVal: MyEnum = "a" or const testVal = "a" as MyEnum The latter passes typechecking with invalid values, both change automatically for me if I refractor the symbol values in VS Code.
- zdragnar 4y agoIt checks fine for me. const testVal = "a" Here, TypeScript infers that it is of type "string", and knows the value, so it is perfectly happy accepting it to ALSO be of type MyEnum. This is the problem- refactoring MyEnum means that testVal is not automatically updated, because the type is really "string" that just-so-happened to duck-type into MyEnum at the function call site. On the other hand, if MyEnum were actually an enum rather than a union of strings, this problem wouldn't have happened.
- trinovantes 4y agoIf you don't want enum's runtime footprint, just use `const enum` Less typing and easier to read than your solution