DEV Community

Cover image for TypeScript Best Practices — Using Enums

TypeScript Best Practices — Using Enums

Stephen Gbolagade on December 10, 2024

TypeScript is not just about validation, It's also about structure and today, let's talk about using ENUMS to save your team unnecessary hours of d...
Collapse
 
tomosterlund profile image
Tom Österlund

I like using enums too for objects.

TS-team however, recommends we use objects instead, like:

Object.freeze({
 Vendor: "VENDOR",
  Customer: "CUSTOMER",
  Rider: "RIDER"
})
Enter fullscreen mode Exit fullscreen mode

enums have some type-safety issues: dev.to/ivanzm123/dont-use-enums-in...

Collapse
 
stephengade profile image
Stephen Gbolagade

This is a good take

Collapse
 
mordechaim profile image
Mordechai Meisels • Edited

No, use string unions instead.

Enums introduce a runtime construct and typescript should only be a compile-time tool.

Unions gives you all the type safety and -- for libraries -- works for JavaScript (i.e. non typescript) projects flawlessly.

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

I get what you mean, but what you say is wrong: It is a compile-time tool, or better stated, a transpilation tool since JS is not compiled by today's tools. Today's tools transpile, bundle and minify, but don't compile.

What you meant to say is that TS should not "write extra code", or at least this is what I think you meant. If I'm correct, that's also wrong: TypeScript, depending on the target version of ECMAScript, will generate code accordingly. By design, TS is meant to support as much as possible all the newest syntax ahead of time, and is ready to shim on the fly.

Finally, there is no absolute "best" enum. String unions are nice, but numeric enums are great:

  • A numeric enum only consume a fixed number of bytes regardless of its value, while a string consumes bytes depending on the string length.
  • A numeric enum can be used as a set of Boolean values when its values are single bits, and both read and write operations are O(1).
Collapse
 
mattchowski profile image
Mateusz Wojciechowski

Not everything needs to be measured in bytes and performance, especially in JS where you're not building space ships or medical equipment.

Dev experience is also really important and enums give you none. String unions are perfectly fine and superior in most cases due to their simplicity and "logicalness" for lack of a better word.

Thread Thread
 
webjose profile image
José Pablo Ramírez Vargas

Not everything needs to be measured in bytes and performance, especially in JS where you're not building space ships or medical equipment.

Apologies, but I call them as I see them: This mentality brings projects to the ground. People who say this most likely say it because they can't optimize, they can't have performance in mind while writing code. These people need people like me doing their code reviews.

Yes, string unions are simpler, but they aren't superior in any way I can think of right now. Do you have a concrete example? This part got me curious. Let's forget about bitmasked enums for a moment and simply talk string unions vs. numerical enums. Do you have a concrete case where the string union shines vs. a numerical enum?

Thread Thread
 
mattchowski profile image
Mateusz Wojciechowski

The fact that they're simpler is superior. Just because a developer uses string unions it doesn't mean they don't have optimized or performant code. Writing performant code doesn't always equal to a successful developer. A successful developer must also keep in mind the developer experience and must be efficient, there is a balance between efficiency and performance, if you find that balance then you're good.

I'm not gonna spend 2 hours fixing enum types in complex cases and looking for workarounds when I can just use string unions and call it a day, when the outcome is the same.

If choosing between an enum or a string union has impact on your app performance then youve chosen the TS is the wrong language for your application.

Thread Thread
 
webjose profile image
José Pablo Ramírez Vargas

Ok, fair point. Just a reminder, as it seems to may have been lost: I am not saying to always go for numeric enums. I just say that it is hard for me to say string unions are the clear superior.

You are correct in that there should be balance, and your explanation makes complete sense. In the point I continue to disagree is that simplicity alone is sufficient to make them superior. For us to continue debating on this topic, we would have to define the term superiority. If you would like to, define it. Otherwise, we can call it a matter of opinion since our concept of "superiority" probably varies.

Collapse
 
sc7639 profile image
Scott Crossan

Came here to say this

Collapse
 
dmitryefimenko profile image
Dmitry A. Efimenko

Enums in typescript are not great. Most of the time when you're thinking about using enums, try using string literal instead:

type Role = 'VENDOR' | 'CUSTOMER' | `RIDER`;
Enter fullscreen mode Exit fullscreen mode

This provides same level of type safety, same intellisence, but less verbose and easier to use

Collapse
 
michael_mannseicher_836f6 profile image
Michael Mannseicher • Edited

I would do it so

const ROLES = <const>['VENDOR','CUSTOMER' ,'RIDER'];
type Role = typeof ROLES[number];
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ironblossom profile image
Ishtiaq Mahmood Amin

Enums are horrible, considering the alternatives that typescript provides

Collapse
 
lexlohr profile image
Alex Lohr

As my previous discussion on the topic shows, enums have their uses and limitations and neither of their currently available replacements is very satisfying. Let's hope that there will be a native enums proposal to TC39 that fixes these issues.

Collapse
 
theoephraim profile image
Theo Ephraim • Edited

Aside from the other issues mentioned, it's often very useful to use an object to store additional metadata that may be needed when using the options. You can use keyof typeof to extract the keys into a type (string union) to be used throughout your code.

For example:

const ANIMAL_DATA = Object.freeze({
  dog: { scientificName: 'Canis lupus familiaris' },
  cat: { scientificName: 'Felis catus' },
});

export type AnimalsEnum = keyof typeof ANIMAL_DATA; // 'dog' | 'cat'
Enter fullscreen mode Exit fullscreen mode
Collapse
 
aloisseckar profile image
Alois Sečkár

Let's talk about NOT using enums in TS
wordman.dev/blog/typescript-enums

Collapse
 
juniourrau profile image
Ravin Rau • Edited

I used to use enum last time, but there were some issues that I faced.

  • increase in the size of the output
  • no proper type safety for string enums

Since then have been using plain object

const Role = {
    VENDOR: "Vendor",
    CUSTOMER: "Customer",
    RIDER: "Rider"
};

// Usage
console.log(Role. RIDER); // Output: Rider
Enter fullscreen mode Exit fullscreen mode
Collapse
 
standiki profile image
Stanley Diki

I'm yet to start using TS for projects but I'm excited to read blog posts around it. This is a great content too. Here's my observation: You are trying to access the key "Admin" but it's not defined in your data structure, won't this confused beginners like me? ☺

Collapse
 
stephengade profile image
Stephen Gbolagade

Oh no...

That was a typo.

It was meant to show how to access the value in the enum object.

E.g

Role.Vendor // VENDOR
Enter fullscreen mode Exit fullscreen mode
Collapse
 
standiki profile image
Stanley Diki

Okay, thank you.

Collapse
 
guilherme_taffarelbergam profile image
Guilherme Taffarel Bergamin

Sometimes it's better to use Types for this kind of stuff because enums generate a lot of unnecessary transpired code (not a big issue if you don't have too many, tho) and because types will more easily resonate with people still using strings for this kind of stuff. It's still forcing everyone to use the correct string too.

Collapse
 
varma_sagi_82f557ba2d8a09 profile image
Varma Sagi • Edited

Enums is almost an useless feature in TS and you hardly wrote about it

Collapse
 
mirkomi profile image
MIrko Miromoro • Edited

I just created an account to tell you that this is most definitely not a "good pactice". You should have educated yourself more before making claims like this. You should take this post down, as it's plain wrong, and misleading...
Don't spread bad practices among js devs, there are enough already...

youtu.be/0fTdCSH_QEU?si=GBfZt8xzmv...

Watch this video of a deep understanding of enums and tell me if you still think the same

Collapse
 
hugohub profile image
Karlis Melderis

If there would be easy fix for this in JS 🤔
Otherwise I tend to agree that enums are obsolete

typescriptlang.org/play/?#code/KYO...

Collapse
 
ozan_bc433c26c42151d9b3cb profile image
Ozan

Please never use enums, it's not a good practice. It's actually a very bad practice, enums in TS work very different to enums in any other language.
If you wanna have the same behavior, define an object with the key/value pairs and set it "as const".

Collapse
 
vrboop profile image
varun-r-boop

Enums are bad in ts they were not made for ts they are not even type safe the better alternative would be to use objects or union types

Collapse
 
tbogard profile image
Erick Rodriguez

Enums has tons of issues. Use as const

Collapse
 
bobbyb profile image
Bobby Bridgeman

If you are storing the result of the enum as a string, it might as well start off as a string. There's nothing wrong with using a constant static string. If you are however storing it as an int or using it as and int value type, enums are good.

Collapse
 
blueiii profile image
Blue

I typically follow the recommendation of Matt here:
https://youtu.be/jjMbPt_H3RQ?t=313&si=dxR47C3MgaB4bt43

Collapse
 
rvraaphorst profile image
Ronald van Raaphorst • Edited

Just what I wanted to say. Thx.

Collapse
 
khaja_hussain_db1f84efe83 profile image
Khaja Hussain

Totally agree. nice explanation.

Collapse
 
betotto_gonzlez_1d7893da profile image
Betotto González

The best practice is not to use them