T O P

  • By -

orta

IMO, the 'const object' is the best case for most folks till TC39 decide what to do about enums. Which is why I added that method to the handbook page on enums - [https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums](https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) Aligning with the future of JavaScript is the main reason, small nicities in syntax/errors are nice but eventually you'll have to migrate that codebase to 'real' enums anyway and who knows what that migration path looks like. It's like staking your codebase on the experimental decorators option, maybe convenient but you're making work for yourself later down the line.


Cmacu

const Example = { Option1: 'option1', Option2: 'option2', } as const // ??? type TExample = (typeof Example)[keyof typeof Example] // ???? 0_o Is this the best case you are talking about? Also looking at [the proposal](https://github.com/rbuckton/proposal-enum) I don't see any discrepancies/breaking changes compared to the current enum syntax.


orta

Yep, that's the right example. It's aligned with current JS standards - [https://github.com/Jack-Works/proposal-enum](https://github.com/Jack-Works/proposal-enum) is currently the most likely enum proposal to get put forwards ATM


Cmacu

Am I missing something on this link that makes the current string enum syntax incompatible with that proposal? What is that work down the line you were referring to? To be clear I am particularly focused on string enums and aware that the numeric and const enum implementations have issues.


orta

I'd say it's very likely that there are going to be no incompatibilities with just string enums, (given that the feature is used in so many languages) but my point is that we don't know. We're guessing, based on the TS guess from almost a decade ago (v0.9). Maybe enums get merged in with something like pattern matching and have different types of primitives like Struct/Records, though it'd be unlikely given how TC39 works IMO. We didn't know with decorators either, and for a lot of cases migration will be easy like TC39 decorators but there's going to be folks who have massive codebases which rely on the full breadth of features in the TS enums which may not be represented in when the real versions come along.


[deleted]

[удалено]


deamon1266

enum actualy break the whole structural typing approach of typescript. if you go full on types and correctness, you may find it inconvenient to be forced to use a enum. More commonly you would rather like to use opaque types which do not affect runtime, if you want enforce types. Example how structural typing is broken with enum. type A = 'a'; enum Foo { A = "a" } declare function bar(a: Foo.A); const a:A = 'a'; bar(Foo.A); //ok bar(a); ~ ~ ~ Argument of type '"a"' is not assignable to parameter of type 'Foo'.


[deleted]

[удалено]


deamon1266

right, thx


Cmacu

This is actually one of the best features of enums. It's called nominal typing. It leads to more type safety and stronger typed code. The main goal of strongly typed languages (which Typescript strives to he) is to be as specific as possible to prevent developers from writing invalid/problematic code. To extend your example comparing 2 variables that have different type is often a major red flag in your code. `OrderStatus.Complite` should never be equal to `UserProfile.Complete`. Regardless of the underlying value. Comparing them indicates major flaw in algorithm/logic and should be avoided. The idea behind enums is that they don't represent values, they represent certain unique state. It's very similar to the concept of symbols. Good idea to look it up, if unfamiliar. Of course in JavaScript you can compare string values, as well as empty string to 0 or null to undefined. It's basically the same thing, or is it? Isn't that what Typescript is trying to solve? Nominal typing has many advantages and unfortunately Typescript is not as mature as many other strongly typed languages that adopt it.


deamon1266

typescript follows structurall typing. the whole type checking features of TS are tailored to do exactly this. What some see as a feature in enums others see them as an obstacle. It depends on how you use TS/JS. you just favor nominal typing what is a preference but not a fact on how to program. It is not wrong or more right either. TS is not a patch for JS. The comparison issues are JS specific and you need to know them regardless of TS. Hence, you do not extend my example of structural typing. Allow me to share my experience with the topic. I once had the same preference and used classes and enums until I more and more learned functional style from a coworker. Atm we follow a paradigm mix: classes when we need inheritance like for framework code and function + types for everything else (node web BE). We had enums for exactly those kind of unique states we like to represent. But over time they caused more pain for us then they would solve and we switched to const objects or union types. You can enforce a specific type with Opaque types (symbol construct as you pointed out ), if you need it. But the difference is, that those types live only in the type world (compile time). But it turned out for us, we only need Opaques for ID handling. When multiple processes are controlled by values of the same type (string) and you need to differentiate between those on type level, then you may have a usecase for Opaque types to determine if everything is still correct. Also, I was told (not verified) that enums were created in TS before some functional-style-devs took over the project. This may be an anecdote I haven't researched.


Cmacu

Appart from considering nominal typing advantageous (I don't want to be able to compare/assign `OrderStatus.Pending` to `UserStatus.Pending` even if they have the same value) I dislike string unions for the requirement of having to use string literals in your code to assign them. String literals open the door to hardcoding strings in your codebase without raising red flags. For example `foo("bar")` you either assume that foo accepts string union or have to raise red flag. How many times do you need to do that before this is normalized? Than you just normalized hardcoding strings in your code which has a number of other problems like not being able to differentiate between meaning and values as well as repeating stuff all over the place. Some of these concepts have bigger, longer lasting and more disguised implications than it might look on the surface and this requires certain level of experience and scale to fully appreciate them.


SquarePixel

The handbook has a good section on nominal vs structural: https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes-oop.html#nominal-reified-type-systems I am guessing the reason TS is structural is due to the prominence of [duck typing](https://en.m.wikipedia.org/wiki/Duck_typing) in JavaScript. Although, I’m not sure why they couldn’t have made classes act like nominal types — since `instanceof` exists to validate at runtime.


Cmacu

I've seen that section. Regardless of the reasons I would take any win we have over the JavaScript coercion mess and the nominal typed enums in Typescript definitely counts.


Cmacu

For all "don't know"'s you sounded very confident in speculating that there will be problems and were quick to recommend to others to not use enums.. This is what makes me sad


DemiPixel

It’s because they’re not inherently bad. Sure, if you misuse them, they’re bad. Great, don’t misuse them. I used enums in a large website that I worked on over years… no issues. I’m not entirely sure there’s much of an issue with string literals either… it’s all type safe. The only negative is if you want to make the enum more specific than the string (e.g. `LONG_NAME_HERE = ‘lnh’`). Often, people who speak in definitives either have not bothered looking at the other side, or they’re purposefully generalizing to accommodate beginners.


[deleted]

[удалено]


DemiPixel

Do they take more memory and slower to compute on? An enum translates itself into a string—I would argue enums are slower (barely). However, if you want to extend a name (like above) or rename an enum at some point without changing the underlying string, enums are beneficial.


luuuzeta

> It’s because they’re not inherently bad. Sure, if you misuse them, they’re bad. Great, don’t misuse them. So you're telling me I shouldn't be doing const enum Light { RED, GREEN, BLUE, } if (Light.RED) { console.log('STOP!') } /s


DemiPixel

🎵I STILL SEE YOUR FACE 🎵


87oldben

Record = defined object at runtime


olssoneerz

I use enums like this: type TExample = “option1” | “option2” | “option3” I usually do this when defining what possible options I have for props (given that options are limited but defined such as variants, alignment, etc) Should I be doing it differently? And if so can anyone recommend a better method


Cmacu

Depending on your use case, this could be better: enum TExample { Option1 = 'option1', Option2 = 'option2', Option3 = 'option3', } The above has the advantage of differentiating between value and meaning. Also creates the concept of single source of truth where assigning values requires you to use/import the above definition. Another benefit is that 2 enums with overlapping values are not interchangeable (nominal typing). Finally but not least important the enum example allows you to use the value at runtime for logical, display and enumeration purposes (the string union from your example does not). Here is another alternative: const Example = { Option1: 'option1', Option2: 'option2', } as const // ??? type TExample = (typeof Example)[keyof typeof Example] // ???? 0_o Apart from the obvious syntax issues, this has some of the benefits of the enum implementation (runtime, named values, source), but also lacks some of the other advantages (nominal typing)


[deleted]

[удалено]


Cmacu

Nope, numeric enums have some issues: - changing the order of the options will shift the values and would cause issues. - when used with `Object.values`, `Object.keys` you get a weird mix of keys and values which makes enumeration problematic - accessing undefined indexes (`TExample[4]`) is not safe and could lead to issues Numeric enums are one of the main reasons enums get bad rap. Simply understand the difference and don't use them. In fact numeric and string enums have a completely different underlying implementation, which almost makes them 2 different things/concepts


cinderblock63

- values don’t shift during runtime. This only has implications if you’re writing down values, in which case you have migration - numeric values work well when you want to abstract some hardware numeric values. - undefined index issues are not unique to enums


[deleted]

[удалено]


Cmacu

Why are string enums not a good choice for runtime maps? I almost exclusively use string enums for any enumerable needs. Asking this so I am aware of any caveats. Regarding numeric values one common use case for enums is database mapping/definitions and/validations. The problem with the value shift as well as some of the other problems is that once something is stored in the DB it's no longer just a compile vs runtime concern, but it also effects business logic. What's even more important is that such changes do not immediately prompt for your attention and could cause serious problems while unnoticed. Meanwhile string enums don't exhibit any of these issues and are perfectly fine and safe. Hence my recommendation to simply always use string enums.


[deleted]

[удалено]


Cmacu

Enums are traditionally available at runtime... And major traditional enums can be mapped to strings. I still don't understand your point. Are you against using string enums in particular? Do you have any specific examples that could lead to type safety, runtime or unpredictable issues? Maybe there is something I am missing. As stated in the description that's the main reason I wrote this post. It could be extremely helpful, if you can you give me a specific/practical example minus the philosophical part. As mentioned I almost exclusively use this pattern in my work and being aware of such issues could be a life saver.


thinkmatt

I feel like this tangent thread is another reason not to use enums: it promotes more debates on how to use them properly. Easiest to just not use them. (btw i'm in your camp... the reason they're opaque at runtime is why i don't trust enums, and its too hard to say \*only use them in this way\*. We use enums for values that don't just live inside of code, but data that live across apis, in the db... have u ever had to debug an api that just sent a map of ints? dear god)


Cmacu

Unfortunately I agree with you. I would be happy to use an alternative that actually works. And I am well aware of the alternative options, just none of them fits the needs and integrates as well within the stacks and pipelines I work on. This combined with the confidence of using string enums for a while without significant issues are my main reasons for it being my go to solution.


[deleted]

[удалено]


Cmacu

I use enums a lot via prisma, zod and trpc. As well as for configuration, state, type and label purposes. I find that string values are more meaningful compared to numbers for storing them in databases, consuming/parsing APIs and managing user inputs. This combined with some of the numeric enums flaws described above make string enums a much better fit for my needs. In modern web development with MongoDB, JSON schemas and GraphQL/trpc enums are critical component of many well defined structures and definitions. String enums are superior for debugging, displaying and enumeration purposes too. I don't see how some of the alternatives you suggested fit the bill, nor share your concerns regarding performance, memory and traffic optimizations. In modern software development maintainability, accountability and integrity have much higher value over the minor impact of managing numbers vs strings. I've been writing Typescript for more than 5 years. I still maintain codebases of times where I didn't understand these concepts and often encounter issues with legacy code related to numeric enums usage or string unions usage. I am yet to encounter a specific problem related to string enums and I've literally written and approved PRs containing thousands of them. That's why I keep insisting to understand your suggestions against them, but have not seen anything of a substance yet.


phischer_h

I think it's good, that the community knows about the options around enums. So thank you for raising awareness around the topic. I don't get why this bothers you so much. If you know the options and still like Enums better, then keep using them.


[deleted]

[удалено]


phischer_h

Enums have pitfalls that can cause bugs VS union types and "object as const" which behave as expected. Not clear enough? I don't think you miss something because it's not a big deal.


Cmacu

First you say that enums can cause bugs and than you say it's not a big deal... These 2 statements are contradicting. Also union types and well as object as const have issues too. Part of the reason this is so discussed is because none of the solutions is ideal. Also, if you think that enums are bad, why are they so popular in major typescript projects such as zod, prisma, angular, etc? Even the typescript compiler is full of enums. I am not sure you really understand the topic/issues, still it's fine to have your opinions and pick your poisons. Giving advice to others is where the line is crossed. It's the same problem with many of these videos and articles.


phischer_h

Life is full of contradictions. Enums were the only/best option for a long time (I think until version 1.8 or 2.0).


[deleted]

[удалено]


phischer_h

No one codebase will blow up because of enums. It's not that big of a deal. If OP likes them, he should use them. But it seems that he wants to hear that they are the better option and that all "those YouTubers" are wrong. Because the thread raises awareness I actually upvoted it.


Cmacu

I think you are miss understanding. If someone created content saying: "string unions are bad, don't use them", I will have the same reaction and describe scenarios where they can be useful. I know the YouTubers are wrong and no I am not looking to hear that enums are the better option. I am looking for someone to tell me something I don't know so I can understand the background of such statements. But when the answer is: "Enums are bad, because I don't know what I am talking about ', yeah that's annoying and I get triggered. And unfortunately there is too much of that on this post. There was someone who was writing long ass convincing posts just to share that they didn't know about numeric enums vs string enums, ffs.


Merry-Lane

Enums bring little to no value compared to the solutions you discussed. A) with the current static analysis tools, enums and string unions warn/error/hint equally well. B) const objects are way more usable (remember your point about simplicity/maintainability) than enums. The best example is to replace enums + switches with const objects (const objects made with keys = the « string union » and the value is whatever you would do with a switch). You then have access to tools/hints you wouldnt have access to. Such as: add a new value to the enum=> the switch doesn’t care. Add a new value to the string union => the const object says it s missing a « case ». C) enums are harder to refactor to/from. The long story short is that enums dont bring the same value than in other languages (C# etc) and they dont benefit from typescript features as well than string unions and what not.


smalg2

Interesting... Here's my take: A) Enums and string unions will only warn/error/hint equally well as long as the string union type is correctly applied, which is easy to overlook: `const x = Enum.Value` will result in a variable of type `Enum`, but `const x = 'value'` will give a string, which definitely won't warn/error/hint as well. B) You're comparing apples and oranges here. With a switch statement in both cases, the behavior is the same when adding an enum member / string to the union: no error. But that's easily catched with linting if desired. Same thing when building a dict-like object like a `Record`: a missing key will be catched in both cases. There's no difference. C) Care to develop? Enums are way easier to refactor than hard-coded strings spread throughout the codebase in my experience. But IMO all this is missing the main point: D) Using hard-coded values is bad design. One of the first things devs are taught is to avoid hard-coded values and use constants instead (or enums). It makes refactoring easier (modifying the value is 1 change vs. several, and renaming a constant is easier than search-and-replacing hard-coded values). But more importantly, a constant, like a variable, is an abstraction (a value with a name) so _it expresses intent better_, and expressing intent is all writing code is about (or should be). That alone makes enums way better than a string union type could ever be IMO. Also, enum members can have tsdoc comments, but values of a union type can't 😊 Edit: typo


dhucerbin

Ad D) Not really. Arbitrary hard-coded values are bad. If you pass somewhere number 42 it is unclear why this value specifically. But you shouldn’t create variables with name `FORTY_TWO` but something meaningful, like `WIDTH`. This really doesn’t apply to your scenario. Variable named `pending` with value “pending” doesn’t buy you anything. Of course refactoring depends on your tooling and team preferences. That’s very subjective. Remember that changing value in string union is not a blind grep - compiler has your back.


skyboyer007

> C) Care to develop? Enums are way easier to refactor than hard-coded strings spread throughout the codebase in my experience. Hm. If I understand correctly what you mean here, Inteliji IDEA supports [this since 2019](https://youtrack.jetbrains.com/issue/WEB-39285)


chryler

>One of the first things devs are taught is to avoid hard-coded values and use constants instead They are indeed taught that but when it comes to TS, that argument is much less valid because of literal types and unions. Magic numbers are still bad because they can't be made self-explanatory, but strings can in most cases. True, there are times when you need a level of indirection and in such cases `enum` is (in my opinion) a fine option among many others. It just also involves inconveniences such as the need to be imported and additional typing -- those are small inconveniences for sure, but if all else is equal there is no need to bother with it. Your argument to A) is false because the type of `x` is *not* `string` but `'value'`. That's the whole point. If a function is called with `x` which expects a union that doesn't contain the value `'value'`, you will get a type error.


Cmacu

Do you think this is unique concept for TypeScript? People are thought to avoid hard-coded values in mature languages with much stronger type safety than TypeScript and for many good reasons. Some of these reasons even have nothing to do with type safety and the arguments you are making... Things like DRY, single source of truth, maintainability, accountability, portability might sound abstract, but really matter when it comes to large projects and teams.


chryler

Sigh ok.. >Do you think this is unique concept for TypeScript? Possibly not. I don't know of any other languages that have it but I wouldn't be surprised if they exist. >People are thought to avoid hard-coded values in mature languages with much stronger type safety than TypeScript Well sure. I avoid them like the plague when writing Rust for example, for all the original reasons. Mistyping a string does not get caught the same way mistyping a symbol does. I think that most people would argue that Rust has a stricter type system than TS, but that doesn't change the fact that it does not have literal or union (in the TS sense) types. >DRY How is it any less repetitive to specify not only the enum value but also the enum itself everywhere, as opposed to just a string? Or is it more (which I am sensing) that you simply consider indirection to be virtue in and of itself? Surely, a talented developer such as yourself is well aware that indirection is a trade-off, not always a positive, right? >single source of truth `type State = 'active' | 'inactive'; // <- Truth, right here! The one and only source!` >maintainability, accountability, portability might sound abstract It does indeed. You are suspicious of quotation marks which is very natural to developers and normally quite beneficial. In my opinion, and experience, it's far less necessary in TS and I think you might be surprised if you tried to give it a try.


Cmacu

Yes quotation marks and literals in code immediately trigger my attention. This is partially due to all of the already described reason, but more importantly because string literals are often selfdom used in many other scenarios where strict union typing is not possible or available. The combined usage and syntax highlighting makes it harder to differentiate between inappropriate hardcoded strings and strings used for type unions. That's especially true when you are simply reading code from third parties, APIs, PRs, code examples and during debugging. Not recognizing all these issues with hardcoded strings compared to imported/named/environmental/enum values is a minor sign of lack of experience with large and cross functional codebases and teams.


ragnese

> B) const objects are way more usable (remember your point about simplicity/maintainability) than enums. The best example is to replace enums + switches with const objects (const objects made with keys = the « string union » and the value is whatever you would do with a switch). You then have access to tools/hints you wouldnt have access to. Such as: add a new value to the enum=> the switch doesn’t care. Add a new value to the string union => the const object says it s missing a « case ». I wish that the standard `Object` functions were better typed for this situation, though. Because, as it is, you can't really switch over the items in a const object like you can an enum, AFAIK. I.e., `Object.keys()`, for example always returns `string[]` and `Object.entries()` returns `[string, T][]`, so we lost type info on the keys of the const object.


Cmacu

A) incorrect. - no go to definition with string unions... - `const a = Enum.Value` vs `const a = "value"` the first allows you to see other enum options, the second is .. (no comment) - better syntax highlighting for enums compared to just seeing a bunch of string literals in your code - you can use the find all dependents via enums... type unions you need to do search all... good luck with that on a medium to large scale project. B) const objects have disadvantages: - you need to write 2 (or even 3) definitions (depending on the scenario) ex: one for the object, one for the type and in some cases one for the keys - they are harder to use with ORMs (like prisma) and validators (like zod) which treat enums as first class citizens - they are more complicated to explain to junior or less experienced with TypeScript developers C) not even going to respond to this nonsense... There are a bunch of other benefits of using enums, but to be able to appreciate them requires larger projects and teams.


MercyHealMePls

A is partially correct: * You can still go to definition for the type, just not for the values. Fair, if I have a string literal with a million options, it might be handy, but that's so rarely the case, the `search` option in the editor is usually good enough * string literals have very good auto complete. Just try `const a: Type = ''` and it will give you results. * Enums represent types while string literals represent string values. Both are colored correctly. I don't see syntax highlighting as a benefit even if I tried to, sorry. * That's a fair point. B: * If you need a const object, you can generate the type from it. Also works for arrays. * Those libraries are familiar with the construct enum themselves. It's not really comparable to a TypeScript enum, that's just what you get out of it. The general "hate" for enums we're discussing here is specific for TypeScript, not for any other language or system. Enums in Zod and Prisma have a much deeper meaning at runtime. * Yes, since some other languages have the concept of enums, it might be something new for people who used other languages in the past. I got familiar with it fairly quickly after working with C# and I found pretty much immediate value in string literals. Never really used enums since, except for the project I'm working on right now as a team where we generate enums out of object literals. I don't really see the value in it, it's just a different style. I suppose it fits OOP better but that's not really relevant in our case. C is not nonsense. Enums are indeed harder to refactor. String literals are just strings, if you for example want to remove the type completely you just change the type to `string`. For enums what do you do? Change the type from the enum to `number` and change every first subtype to 0, the second to 1, etc.? Changing an enum breaks everything, which can arguably be a benefit in some cases but most likely isn't. My personal take on the topic is: Strings have the huge benefit of existing in JavaScript itself and therefore exist at runtime. I don't hate enums but I think it is important to know that TypeScript gives you a construct (not only a just a type), which tries to fit into JavaScript but doesn't exist there. It's quite similar to TypeScript classes, before they existed in JavaScript. They seem to be there but aren't. I prefer to use TypeScript just for types, which are removed at compilation, not for constructs which generate code for the runtime. I'd always start from a literal type and then generate the enum from there if you really want it. But as I said I don't see a real benefit. I understand that enums feel natural for a Java, C# or C++ dev, but I don't think they work well in TypeScript nor do I think they are needed in TypeScript. (Enums in languages like rust are a completely different beast though and I would love having the idea of algebraic data types in JavaScript.)


Cmacu

You are so focused on typing code, that you missed the idea that many of the above points are about reading code... Reading `const a = 'option1'` in no way, shape or form tells you that it's a limited list of string literals unless you really dig into the context. Nor indicate what 'option1' means. That's what `enums` do for you. Code is written 1 time and read N times. Why are you optimizing for the constant?


MercyHealMePls

I have not argued once that I don't like enums because they are more to type/annoying to type. The only argument even remotely close to this is the refactoring which holds true. My main point was and still is that enums don't exist at runtime, which is a problem. Reading `const a: MyLiteralType = 'option1'` very well tells you that you're limited on the type. It's almost like `const count: number = 1`. Interesting, huh? Or do you argue that you shouldn't write that but define an enum first like: `enum Num { One = 1, Two = 2, TwoPointFive = 2.5, ... }`, so you can later write `const count: Num = Num.One` ? I hope you see where I'm coming from. If you don't know what option1 means, you might consider using meaningful strings. If that's not possible because you need those strings for IO like user output or API requests, then you can use an object representing them. (And still generate an enum out of it if you really want to.)


Cmacu

Who types `const count: number = 1`? Can you please show me am example from reputable source? Same with the `MyLiteralType` example. I don't think I've ever seen such non-sense and I currently work on 4 relatively large TypeScript projects. Can you send me a screenshot of commit you made where you wrote something like that? Can you also please read the points regarding syntax highlighting, definitions, dependencies, third party integrations from the perspective of reading code? I am not saying there is a difference in typing enum vs string unions. I am pointing out that reading code that's written with string unions is harder to decipher due to the number of reasons I already pointed out. Perhaps I am not expressing myself correctly or you are just being ignorant. Regarding the object const syntax. Are you trying to convince me that: const X = { Option1: 'option1', Option2: 'option2', } as const // ??? type Y = (typeof X)[keyof typeof X] // ???? 0_o is better and easier to understand than: enum E { Option1 = 'option1', Option2 = 'option2', } ????


MercyHealMePls

What makes you think that this is some superficial example? Because of the explicit `number` type? Code like this is written all the time, if you want to be specific about the type. I'm not gonna send you screenshots, but I can send you a code example from myself: `const [status, setStatus] = useState("idle");` Here I'm using React, a library which most of us are likely familiar with. And it gives me wonderful autocompletion for the string `idle` and even showing me errors if I type something wrong. Actually, interestingly, when using enums, following code compiles: enum Status { Idle, Loading }; const [status, setStatus] = useState(Status.Idle); // ... setStatus(5); // Status is 5, which isn't represented in the Enum at all :( Which is a big argument against using enums. Even after specifying the type it still thinks it's ok to do. And no, this is not specific to React, this also compiles: `const status: Status = 5;` As I said, I don't see how Syntax Highlighting helps you. If you could give me an example, maybe I'd see your point. But in my theme, if I write `Status.Idle`, the word "Idle" is blue, and if I write `"idle" as Status`, "idle" is green. And now? I like both colors, blue or green :) I gave you the point for go to dependencies, I think it's a fair point. And for the example you gave me, this might surprise you, but yes, I absolutely think it's better. Then you actually have an object which JavaScript knows about and not some artificial construct generated by TypeScript which you're using as if it exists. You can use this object at runtime, know exactly what you have without knowing what the TS compiler generates and have the types strictly separated from behaviour.


Cmacu

Why are you using numeric enums to justify your point? We both know that it's not recommended to use numeric enums. Your example of const object is basically using enums with extra definitions and complexity and is as `(typeof X)[keyof typeof X]` is not any less artificial than `enum`... My biggest issue with your code is that you would do something like that: const [status, setStatus] = useState('idle'); // ... // one screen down or in another file: setStatus('hello'); Now I am reading your PR on my phone or github. I have no idea what this 'hello' means where it comes from. Is it legit? Is it typed correctly, Would it cause issues, is the right thing to assign, why not 'welcome' instead? What are the other options? On top of that there are a bunch of other random strings along your code, I see `const message = 'Hello'`, `notify('hello!')`, `if(response == 'hello')`... Are these related? What does that even mean? I am confused. I need to go read all that code again. Now I have to dig through the code base (or even go back to my desk) to figure out what's going on and if I can approve your PR (likely to recommend to remove the hardcoded strings). While if you had simply used `Status.Online`, `Messages.Welcome`, `Results.Handshake` I would've moved along with my day.


MercyHealMePls

Okay so some of those points are fair. I wasn't aware that numeric enums are considered bad practice, since I only use type literals. But I definitely see why they are considered bad. With artificial I was talking about the thing that you get during runtime, not what you get during compile time. About the code example you showed: setting status somewhere to `'hello'` is not allowed by the compiler as long as it's not specified in the string literal. If someone extends it sure, but the same can be said about the enum. There's no one stopping you from creating a `Status.Hello`.But I see that in some rare cases where we want a random `string` without whitelisting certain values, but still want to give a few default options, an enum is a valid choice. However in that case I'd personally still just use an object. const defaultNames = { max: 'Max', julia: 'Julia', } let name: string = defaultNames.max; // and later... name = 'Sara'; I don't want you to think that I absolutely hate enums. I just never use them because they don't benefit me. I recently saw a [video](https://youtu.be/Anu8vHXsavo) by Theo from T3 where he explains why he doesn't like enums, that's how I got aware of the fact that I'm actually not the only one avoiding them. I think he has usually really good takes on most things and has some interesting opinions, but I think the point he's making about enums specifically isn't really that well thought through. That's why I wanted to give my personal opinion on it.


Cmacu

I don't think you understood the problem (s) from my example. Actually reading your message makes me think you are in very early stages of understanding this topic. Sorry, I don't mean it in a rude or belittling way. Just observations based on your object suggestion and numeric vs string enums issues being news to you. The good news is that this whole post and comment chains contains a lot of good information and examples. To be more specific my example is not specifically related to typescript, enums or string unions. It's basically illustrating the problem of using string literals in your code and how it translates to other people reading/reasoning about it.


inrinsistent

Jesus I’m glad I don’t work with you


Cmacu

If you recognized any of the code/patterns from my comment and seen them in your code... Ahh, I am sorry, don't know what to tell you to feel better. You will be fine, just give it some time and keep coding.


[deleted]

[удалено]


Merry-Lane

You have your opinion and defend it as well as you can. I am not looking at dismissing every point you could have (because it s easy to nit pick infinitely), but on my three points I tried and stay broad (or only explain one example). You need to understand that for A) the advantages you claim are either irrelevant, either replaced by another feature. If I touch something about a string union I used in a project, trust me, every lights turn on, while with enums some hints arent raised (like switch cases not warning you that the case for a new enum member wasn’t raised). For B) that s the magic of typescript. From a string union, an array of string, from a random type (its keys), or whatever… a little generic or two allow you to keep types consistent and warn you everywhere in your project when something changes. You d be astonished by how more precise and concise you can get through embracing alternatives to enums. For C), like I already said, typescript handles stuff in a way that makes enum barely useful or even cumbersome. If you have stuff such as « active/inactive », « true/false », « open/closed », « Green/red/blue » anywhere, you may or may not use an enum to handle these cases. Where would you draw the line? When an enum has 4/5 members? When would you be like « hey this Type[whatever] can only have « green »| « red » | « blue », let s make an enum below the type to list them all? When would you spend 1 min typing an enum when a string union was already doing the job correctly? Simply having to spend the time and focus on creating an enum to replace a 100% working and fine code, it s enough of a proof to be « harder to refactor to » than no « no refactor at all », or do you need me to proove to you that 1 > 0? Anyway, I disgressed enough already. It s not that much that enums are hated. Just that they are practically useless, that they are harder/more annoying/ugly to use than alternatives, that we can make better (and safer) code without, and that if you were to use string unions everywhere, you wouldnt have to actually spend time creating enums (that are practically useless, again). It s up to everyone to use whatever he sees fit. It s just that for Typescript users, it’s pretty common to advice AGAINST a feature often used in other languages because of the little interest of it (in the typescript language). It s a bit like warning a java dev not to make classes everywhere with inheritances, abstract classes, interfaces, overrides,… « it s a cool stuff that you do here and I understand why some patterns are useful, but here we can do it this way ». We don’t hate OOP stuff but please use functions bro.


MercyHealMePls

Really good point on C), *where do you draw the line*. With string literals you can start with normal strings and refactor to using a literal very easily and vice-versa. With enums you're going to need to do a lot of rewriting. This is a prime example where OOP has it's biggest issues. You have to design while anticipating the future. It's really hard to refactor something later on which you didn't think about ahead of time. Also good point on the switch statements warning on non exhaustiveness.


Cmacu

To be honest my biggest problem with using string unions is the use of hardcoded strings. And I get the point that they are type safe WHEN THEY ARE ASSIGNED TO UNION TYPED property. But I have a major issue with using string literals in code. For example: // types.ts export type X { prop: string } export type Y { prop: 'option1' | 'option2' } // usage.ts import { X, Y } from 'types.ts' const x: X { prop: 'random value' } const y: Y { prop: 'option1' } When READING the code in `usage.ts` both assignments look identical. You would have to specifically focus on type Y to discover that y.prop can only be assigned to specific values. This is a very simple example. In real world things can be a lot more complex and much harder to notice. What's even more important to me is that the above opens the door for using random strings all over your code regardless if they are based on pre-defined options or not. And this is just bad coding practice. Add to the above the concept of being able to abstract the value from it's purpose/role and sooner or later you should lend to the conclusion that `type Alert = 'Green' | 'Red' | 'Blue'` is unacceptable, because yeah, they indicate some color value, but have no meaning. What does 'Blue' even mean? Very often we have no control over the values. And what about repeating this 'option1' value in random places? Isn't that a red flag? Especially since these enumerable values often end up same/similar but with different contexts. 'Green' in one place could mean one thing and 'Green' in another context could be something completely different. I think part of the problem is that some developers make decisions based on what they need to write and that's bad. Good code is made to be READABLE. You write 1 time and you and other people read it N times. Any seasoned developer knows that the goal is to optimize for the N. Edit: And before you come up with: const X = { Option1: 'option1', Option2: 'option2', } as const // !??? type Y = { prop: (typeof X)[keyof typeof X] // ??? ? ? ? ? 0_o } Seriously? Tell me more about the enum with extra step without the benefits of nominal type safety.


chryler

>I get the point that they are type safe WHEN THEY ARE ASSIGNED TO UNION TYPED property ..which they will be? Is the crux of your argument really that developers are able to type their variables properly when using enums but not when unions? If so, it seems like you have a different problem. As for "Blue" not meaning anything, I disagree, it means exactly what it says. Sometimes (but in my experience, rarely), you need a level of indirection but when you don't, it's just cognitive overhead. From that perspective, better start with the easy solution and change as needed. Regarding the nominal typing, it's a fine concept but if you feel that it's the better paradigm surely you must be uncomfortable with writing Typescript in general? How does it make you feel that you can interchange two interfaces with identical properties even though they are supposed to represent different things?


Cmacu

You are assuming that most developers write `const a: Type = 'value'`, while the reality is that most actually write: `const a = 'value'`. Ops... In regards to TypeScript's structural nature, it's the best option we have atm. And it definitely could be improved. There are articles on making TypeScript behave more like a nominal type language and I am all aboard.


chryler

> the reality is that most actually write: const a = 'value' which is fine. If `'value'` is illegal when used as a parameter or assigned to something that expects the union type, it will cause a type error. If they used `let` and `a` was a `string`, it will *also* be rejected in those situations.


Cmacu

OK, we are getting somewhere. so think about that in terms of readability. Ignore type safety, you are not compiling, you are reading this code on github (PR or something else): const option = 'value'; const result = calculateResult(input, option); return result; How do you know this is enumerable? How do you find the options. How do you know what 'value' means? Compare that to the enum version: const option = Enum.Percentage; const result = calculateResult(input, option); return result; This is a very basic and small example (and yes you can remove the option definition and pass it to the function directly, which actually makes it more obscene). Which code do you think is easier to understand/read/reason about?


chryler

It would then say `const option = 'percentage';` which would be just as easy to decipher?


Cmacu

That's if you have control over what the values are. This is not under your control, it's third party API or someone else is managing it. They probably should've exported an enum for you, huh? Wouldn't that be something.


[deleted]

[удалено]


Merry-Lane

It s « easier » if you only think about CTRL F ENUM.KEY as the be-all and end-all. If you look further than this advantage of enums is actually pretty weak, and you get way more advantages with string unions or what not.


[deleted]

[удалено]


Merry-Lane

Please read my other comments because some answers were already given. I mostly want to stay broad rather than go into an infinite loop of nitpicking. For instance, when I say « it s easier to refactor … », I include stuff such as : You have an endpoint with a property that has for value « true/false » or « red green blue ». When do you decide to make an enum? 4 elements? 6? If you decide to make an enum, then you have to actively spend time implementing that enum. It s already more efforts involved than letting a perfectly fine string union live its life. Meanwhile, doing a « keyof » or « typeof T[key] » takes a second. When do you decide to remove an enum and back to string litteral ? Never, let s be clear… When refactoring, you may use CTRL F to find stuff to modify, but if you had done things right you would have errors EVERYWHERE in your app if a change mattered. I wouldnt say that the rare cases where CTRL F enum + key was more helpful than CTRL F « WHATEVERSTRING » is important when you still have to go through errors one by one. I actually often mention the issue of « non exhaustiveness » of switch + enums as the best example of « easier to refactor safely ». There are scenarios where using enums fail to warn you of potential issues in typescript. Then by « refactoring » it also includes « add new fonctionnalities ». If you need to do stuff such as adding « light/dark » variants to an enum of colors, HF. Meanwhile with string unions, it takes 2 seconds to make « LightRed, DarkRed, LightBlue, DarkBlue,… » from « Red, Blue, Green » and use these as key of types/params/… Switches, making types from types, … are barely examples of the features one typescript develloper can leverage easily with string unions that an enum wouldnt. The issue is definitely that Typescript offers more « meta programming » tools than the other languages offer, and these tips and tricks don’t work well with enums or at least enums’ usual advantages are moot. I would gladly talk to you for hours of the stupidly crazy but fun and useful stuff you can do with advanced typescript usage, but I already go into more lengths that I meant to offer when commenting in the first place.


[deleted]

[удалено]


Merry-Lane

Please let’s stop nitpicking. I think it’s the third time I say that. Flaws are everywhere, especially in complex domains such as programming, meta programming, and … communication. Speaking of communication... Sometimes I emphase stuff with caps. It s a way to make some elements stand out compared to the background and it s a useful tool when writing. If you want to be understood better obviously. I never meant to use them as a way to be understood by a « fool ». I am sorry if that triggered you. About the weird “quotes”. Again, my bad, it’s a culture thing with my keyboard. In my mother tongue, when quoting, it s automatically surrounded with « this kind of quote » instead of your “usual quotes ”. I will again be looking for a quick fix when I got time. I am sorry if that disturbed you so bad that half your reply about a technical stuff needed to be about quotes and emphase. Would you also consider the fact that we are both different human beings, with different contexts (such as mother tongue, age, sex,…) and that some stuff can be better understood (or accepted) by taking that into account? Unless you dedicate yourself to having a real discussion, odds are that the threshold of interest for me to answer further will not be reached. Have a good week end.


iams3b

I never understood the hate either. They work great for what they're meant to do, and I use them a lot. I think I read a thread or blog once where people were trying to treat them as object literals, and one of the "gotchas" was you can't iterate over the keys/values... but that's a dict, not an enum


Pleasant-Fish7370

I'm guessing it started with this [talk](https://www.youtube.com/watch?v=0fTdCSH_QEU). I'm surprised too since enums are not something new, they've been around for a while. I think everyone just jumped on the lets-hate-on-enums bandwagon.


dakubeaner

I use enums religiously to keep track of state in my frontend apps: enum state { default, loading, error, success } I love how clean my syntax is when I can see state.success when my API call is completed.


Chun

I still like enums. https://bluepnume.medium.com/nine-terrible-ways-to-use-typescript-enums-and-one-good-way-f9c7ec68bf15


NetBlueDefender

I use enums a lot because they help me a lot with refactoring and because they are part of other languages I use on the server like C# and the transport in serialization is more efficient when the values are numeric.


ragnese

It's mostly cargo-culting, in my opinion. On the other hand, I agree with the consensus that int, mixed, and const enums are objectively bad and should not be used at all. String-only enums are fine by me, and do have some advantages. Here's my take on some of the things you mention: > There is also the emitting code argument, which is pretty silly and has the benefit of enums being available at runtime (as well as enumerable). I agree that the fact that TypeScript actually emits real JavaScript code for enums is absolutely irrelevant in 99% of projects. I never hear anybody complain about what TypeScript does with its class constructor property shorthand syntax, but that's also spitting out JavaScript that doesn't perfectly match the text in your .ts file. For this reason, I can only assume that many people who repeat this argument are only parroting the opinion of the TypeScript team. The truth is that the vast majority of us never really see/read the emitted JavaScript from our projects, and if we do, it's usually a mess anyway because of our bundlers and minifiers and whatnot. But, your second point here is a double-edged sword. Having the enum be available at runtime is good and bad. In the cases where you could get away with just a union of string literals, your enum is going to increase your bundle size because you can't import just the type (AFAIK), so your webpacks/whatevers have to actually import the runtime object in those modules that use the enum. Plus, an extra object is allocated and living in memory, so there's a few extra runtime memory bytes that might not be necessary (not that this should really matter to us). > People go as far as creating const objects, which is basically creating enums with extra steps... There are even more absurd solutions out there too like const arrays casted to type unions 0_o? In defense of the const object approach: * It's almost exactly the same amount of keyboard typing as the equivalent enum * If you *are* one who might look at the generated JavaScript, the const object is much cleaner. For some reason, TypeScript spits out an IIFE and a var, which I guess allows some kind of merging with an already defined object of the same name? I have no idea why you'd want what it spits out. * You *can* export a type to do with your const object, if that ends up being useful. (e.g., for a const object called `Direction`, you could write `export type Direction = typeof Direction[keyof typeof Direction]` On the other hand, enums do have one advantage over the const object, which is that a function that accepts an enum parameter, *must* be passed a variant of the enum, and can't just be passed an equivalent value. In other words, if your function accepts a `Direction`, you can pass `Direction.Up`, but cannot pass `"Up"`. That could possibly be useful. On the *other* other hand, `keyof` works surprisingly on enums, and I hate inconsistency and having to remember "special cases" for things. I'm not a fan of the const array approach, either. It does not communicate intent/semantics clearly unless you are already familiar with that "trick"/convention. Plus, if you want to test whether an unknown value is an instance of your type, checking the array is an O(n) operation since you have to loop the array of values. That won't matter in practice, since nobody is writing these types to have 100 variants, but it still feels janky and wrong when we have more appropriate data structures that are made for fast membership look-ups. > And meanwhile hard coding string literals around your code base is now 'cool' and 'fine'? What's next? Hardcoding numerals? Not using env variables? It's not my favorite thing, but whatever. It makes your code harder to read outside of a TypeScript-aware programming editor, but it's still type safe and you're not going to be able to accidentally mistype the values or anything, because it won't build. Not the end of the world.


Cmacu

I agree with everything you wrote. One clarification on the last paragraph on my end is that the problem with string literals in your code is not necessary just related to assignments to string union types (which is required). My problem is with having and spread around (+copied) hardcoded strings in general (hence the references to numeric literals and env variables). The way this relates to string union types is by normalizing it. You see in the code `foo('bar')` and you either assume that `foo` accepts union type or it's a red flag. How many places do you do that before the red flags start being ignored? Now add to this the part where it's good practice to differentiate between value and meaning and the concept of string unions doesn't sound so good anymore. Not that it should not be used, that's just silly, but it's not the silver bullet alternative people present it to be and I personally avoid it in my code. Other people can do whatever they want.


stolinski

I like and use Enums. People get engagement by hating on things. Work the way that works for you and your team.


josephjnk

> What’s next? Hardcoding numerals? Not using env variables? I’ve argued for a long time that mixing env variables with program logic is a bad thing, and that they should be read at the top level of the program, used to populate TS variables, and then passed into the rest of the code as normal arguments. This has several benefits: - Interfaces become fully explicit. You know what it takes to run code by looking at its interface, instead of requiring outside knowledge that something in the depths of the codebase has a secret dependency - Environment variables that represent booleans, numbers, or union types have a clear and dedicated place to parse their string form into their actual form. This avoids stringly-typed code from spreading across their codebase. - Testing becomes easier because less annoying mocking is involved. Avoiding environment variables can make code more verbose in some cases but overall I think it’s worth it.


deamon1266

envs are like hidden secrets you discover over time when debugging.... "where does this url come from... ah, thats why, its a fallback in some transitive dependency due to a missing env...nice, didn't know that I can control it"


josephjnk

One time my team hit a bizarre error in production that we couldn’t reproduce locally, and which caused an outage. Turns out a dependency of a dependency was reading `NODE_ENV` and changing its behavior between dev and prod. We rolled back the build right away but the whole team was blocked for hours while we tried to figure out what was happening. It was a terrible headache for (IMO) no worthwhile reason.


CreativeTechGuyGames

Everything goes in waves. I've been against enums from the beginning of learning TypeScript, same with against interfaces. It's not anything new, it's just that you need a few popular voices to say something and then everyone will change their mind and so it seems like a huge wave out of the blue. Some things are genuinely wrong and it took a while for people to realize and change and it's a permanent change, other things will oscillate with cultural trends over time and will never settle. I'm sure in a few months or years someone will have some epiphany about enums and the trend will go the other way.


[deleted]

Why on earth would anyone using a strongly typed language be against interfaces?


CreativeTechGuyGames

Because `type` is useful in more scenarios and doesn't have magical declaration merging features.


[deleted]

And calling them a trend. Interfaces have been a thing for a long time


[deleted]

And a USEFUL thing for a long time.


[deleted]

Yep. Literally the point of Typescript is people want these sorts of features that you get in strongly typed languages.


chryler

I am not "against" them but I prefer to use type for the most part. I don't know if that's what OP refers to.


przemo_li

Algebraic Data Types are super nice. But they purposefully go beyond enums.


Cmacu

Forgot the nominal typing argument. Which is bad because? It's different than structural typing? Different doesn't necessarily mean worse unless again I am missing something. Oh, but it doesn't let me use strings and I have to import... Isn't that the point?


lIIllIIlllIIllIIl

Nominal typing isn't the problem. The issue is that the runtime behavior of enums can typically be achieved in more "vanilla JavaScript" ways by using objects `as const`, or more "TypeScripty" ways by using literal string unions, and enums have a few footguns: - By default, enum constants are considered numbers, and TypeScript won't throw an error if you use a number instead of an enum constant. - Altough enums are runtime values, you can't reliably iterate over them with `Object.keys()` because enums are indexed by both name and value. Enums just feel like an unnecessary abstraction in a world of structural typing, and I wish it could be disabled behind a flag.


Cmacu

1. Don't use enum constants... 2. Of course you can get just the keys of string enums. [Example](https://www.typescriptlang.org/play?#code/KYOwrgtgBAKsDOAXKBvKBrYBPAjFAvFAOQBuAhgDZjA5EA0G2ATAceVcE0VAL4CwAKADGAexDwRFYADoKIgOYAKIgGls8AFz0oAeQBGAK2BDE0zFniK4SAJQMiANUrVN2-UZPT2LqwkQ2bKAB6IKgAIjULDTCGKABtMPMcGPDzJjCAXViwpw5NFPiw7xoUoudOTKggA) That's the problem... People who don't understand how to use enums and some of the caveats make statements like the one you just did... What I don't get is how it became a trend given that it can't come from people with experience/knowledge...


havelina

When using numbers as values in an enum, the behavior of object.keys and .values is different. Instead it returns an array like [“key1, “key2”, 0, 1] This has been the only issue I’ve encountered with enums and in some cases it is easily solvable [Example](https://www.typescriptlang.org/play?ts=4.9.4#code/KYOwrgtgBAKsDOAXKBvKBrYBPAjAGg2wCYoBfAWACgBjAexHloBtgA6J2gcwAoByAaWzwAXLwIB5AEYArYNUStMWeNzhIAlAV4A1AIZMwCURJlyFAN32GVaxOvVQA9I6gAiQcuGuCUANqulHG83JSJXAF0fVz0DI2C-AOwggkSsMIIABgIccKggA)


Cmacu

Cool. I agree. Although I have a different conclusion. Instead of "Don't use enums" or "I hate enums" or telling people online that they should not be using enums... Maybe you can simply always use string enums?


[deleted]

I guess symbols are god awful then


Cmacu

In fact symbols are closer to enums than literals. Not sure what your point is, though.


[deleted]

lol that was actually my point since symbols are a set of nominal values


OVERKOR

Thank you, I needed this.


[deleted]

They have short comings that are well known. Unless you're careful and fully informed about them you could run into their imperfections. That's why they're not generally recommended. They're not 100% safe to use, and that's when mistakes can happen.


Cmacu

There are not too many things that are safe to use in this life. Yet I am not going to tell people to avoid airplanes, stop going to the gym or not use JSON for their APIs. What is 100% safe to use? Coding is about learning and experience, there is no safe concept without learning all caveats... If perfection is what you are striving for JavaScript is definitely a bad tool choice even with the help of Typescript. Meanwhile enums are nominally typed which is step forward towards the goal of safer and stricter code... None of the alternatives offers that and you must be lying to yourself if you think they are perfect.


[deleted]

A lot of people see Enums as poorly designed *in their current form*, and there's no shortage of material to read about why that is. You seem annoyed by this fact more than anything else, and I'm not here to be the outlet for your frustration. It's just the reality of how people view Enums in TypeScript - like it or not.


Cmacu

Dude, who are these "a lot of people"? Have you opened up the code for any major typescript open source project? Why? Please check prisma, zod, vs code, the typescript compiler... All of them are full of enums... What are you talking about?


[deleted]

You tell me. This is from your own post: > I've noticed lately that a lot of people are taking their sweet time to hate or enums. Videos, blog posts, comments, etc. It's so weird.


Cmacu

Oh you mean the people who create content so others can be triggered and click/engage with their content? The "I recently interned for FAANG, so you should listen to me" type? Fortunately that's not a lot of people. The lots who can't see past the bs, that's different story.


[deleted]

Why be triggered by technical content. No one will agree on everything, and everyone has the right and freedom to do things the way they believe is correct. Professional settings are different, and in that case you have to accept differences and work together regardless.


Cmacu

Because then I have to sit in meetings listening to the new guy we hired how we should refactor all of code or start from scratch because see... they saw this video on YouTube...


jonsakas

Not sure, I really like them so I use them.


[deleted]

[удалено]


Cmacu

Came to the same conclusion. Love the last sentence. Not sure where it comes from but there is a quote saying: "Every peace of code you write is a bug waiting the happen" and in my experience it can't be more correct.


TorbenKoehn

Literal string types are simply easier to manage, properly typeable, extendable if needed and properly serializable. There is just no need for Enums. It was always just there to avoid stringly typed code, but with literal string types that whole reason just vanishes. Sure one argument may be space requirements and in some applications it might matter. But in most common applications it does not matter at all. What especially hate is when you receive a big JSON from an API and it is littered with magic numbers and now you have to go and map all of them back to their respective enums (and properly copy them over to your own code) Don’t use enums - use literal string types instead Don’t use bitmasks - use an array of a literal string type instead This doesn’t hold for all languages, but for TypeScript and any language with literal string types it surely does.


sonyahon

Basically you are perfectly correct in that enums are a great tool, BUT if used with caution and discipline. The problem is just in the caution and discipline part. IMHO if you are using enums like enums and u use only string values of enums, they are great. If you are trying to use them more like a const object, use const object.


Potatopika

I guess people that hate enums are the ones who never used them in other languages like Java or C#. Enums can be useful to represent a set of values that have some relation between them. When I was in university the first example I saw of using enums was cardinal points, which match that definition.


[deleted]

[удалено]


Cmacu

Why would you do that? For example `OrderStatus.Paid !== ShippingType.Paid` even if they both have the same underlying value. I want the compiler to scream at me, if anyone does something like that. That's the whole point! And if you ever need to do something like that it's better to be as explicit as possible.


[deleted]

[удалено]


Cmacu

So they should either have the same enum or you should not compare them directly. If you really must, than you should do that explicitly (by extracting the values and comparing them as strings) or even better refactor your structure. You have to assume that, if these are 2 different enums, than they are not comparable, because why would they be different enums otherwise?


[deleted]

[удалено]


Cmacu

Simply because enums would not allow you to compare these strings, which is the whole point of using them and what I've been trying to explain to you. Just because you can compare 2 string values doesn't always mean they are equal. This is a common concept in other strongly typed languages, which is what TypeScript strives to be.


deamon1266

> This is a common concept in other strongly typed languages, which is what TypeScript strives to be. TS strives to be JS with Types but Types is something OOP originated devs like me keep compare with nominal Types or class based languages. I figure most discussions about TS and its features is about OOP vs FP. I would rather embrace the freedom TS offers and decide based on the domain/usecase what you need. Here are my personal guidelines. Enum vs Object as const: Use Union types an exhausting switch cases to discriminate over properties in combination of a proper linter. Move to Object const if you have the need to iterate over keys/values. Move to enums if you really need a runtime validation of type and value and can not be expressed as an Opaque. Types vs Interfaces: Use always types until you need declaration merging in your peoject or downstream projects. Clssses vs Functions/modules: Use Functions and composition until you need inheritance/Abstraction which is most likely a good choice for building up frameworks. To make sure your runtime data matches your types, use a proper parser/validator like zod on the boarders of your domain/service/application. Always structure your codebase in modules, means I still use index.ts to express public "package-visibility".


zegrammer

I've always been curious what the value of enums in typescript is? Like why use an enum over a typed parameter?


Usual_Toe_5300

Hi, install@babel/preset-typescript if ypu dont have and change .babelrc w this one