DEV Community

Cover image for You might not need TypeScript Enum
Muhammad A Faishal
Muhammad A Faishal

Posted on • Edited on

You might not need TypeScript Enum

In TypeScript, there is a feature called Enum which is not a type-level extension of JavaScript. Enums allow a developer to define a set of named constants.

enum EDirection {
  Up = "Up",
  Down = "Down",
  Left = "Left",
  Right = "Right",
}

// Using the enum as a parameter
function walk(dir: EDirection) {}

walk(EDirection.Left);
Enter fullscreen mode Exit fullscreen mode

But, on the other hand, we may not need Enum as TypeScript team says on https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums by using an object with as const.

const ODirection = {
  Up: "Up",
  Down: "Down",
  Left: "Left",
  Right: "Right",
} as const;


type Direction = typeof ODirection[keyof typeof ODirection];

function run(dir: Direction) {}

run(ODirection.Right);
Enter fullscreen mode Exit fullscreen mode

So what's the difference between Enum and Object? I'll discuss the difference in Data Types, Bundle size, and How to use aspects.

Data Types

Enum

TypeScript provides both numeric and string-based enums.

// Numeric Enums
enum UserResponse {
  No = 0,
  Yes = 1,
}

// String Enums
enum UserResponse {
  No = "No",
  Yes = "Yes",
}
Enter fullscreen mode Exit fullscreen mode

Constants

While Constants can cover an object with string and number property values including all data types.

// Number
const PI = 3.14159;

// String
const GREETING = "Hello, World!";

// Boolean
const IS_ACTIVE = true;

// Array
const COLORS = ["red", "green", "blue"];

// Object
const PERSON = {
    name: "John",
    age: 30
};

// RegExp
const EMAIL_PATTERN = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;

// Null
const NO_VALUE = null;

// Undefined
const UNDEFINED_VALUE = undefined;

// Symbol
const UNIQUE_KEY = Symbol("unique");
Enter fullscreen mode Exit fullscreen mode

Transpiled Size

I used https://babeljs.io/repl to know the size after the code has been transpiled.

Enum

enum Color {
    Red = "RED",
    Green = "GREEN",
    Blue = "BLUE"
}

// Transpiled Result
var Color = /*#__PURE__*/function (Color) {
  Color["Red"] = "RED";
  Color["Green"] = "GREEN";
  Color["Blue"] = "BLUE";
  return Color;
}(Color || {});

// Size: 153 Bytes
Enter fullscreen mode Exit fullscreen mode

Constants

const COLOR = {
    red: "RED",
    green: "GREEN",
    blue: "BLUE"
} as const;

// Transpiled Result
const COLOR = {
  red: "RED",
  green: "GREEN",
  blue: "BLUE"
};

// Size: 65 Bytes
Enter fullscreen mode Exit fullscreen mode

How to use

An Enum named EDirection and an object named ODirection refer to the same thing as what we talked about earlier.

Enum

walk("Left");
// This shows an error ❌
// (Argument of type '"Left"' is not assignable to parameter of type 'EDirection')

walk(EDirection.Left);
// This works well ✅
Enter fullscreen mode Exit fullscreen mode

Constant

run("Left");
// This works well ✅

run(ODirection.Left);
// This works well ✅
Enter fullscreen mode Exit fullscreen mode

Conclusion

Based on several aspects I've discussed earlier, we can replace Enum with Object. Object has the flexibility for defining various data types, has a smaller transpiled size, and can detect both property values or property access.

So, it's important to remember that not all cool features are the best choice. Always assess the aspects you think important. If a feature doesn't have any negative impact, then you can confidently use it.

Top comments (21)

Collapse
 
wraith profile image
Jake Lundberg

Great topic choice!

I used to love enums, but once support for as const was released, I stopped using them entirely for the exact reasons you laid out here. I never really liked that enums were the one thing in TS that didn't get stripped out during build...instead, it just gets mutated and added to the bundle.

Nice explanations! Keep up the great work!

Collapse
 
maafaishal profile image
Muhammad A Faishal

I'm glad to know that!

Collapse
 
lexakaren profile image
lexa

I found your post about TypeScript Enums really interesting and thought-provoking. It's great to see different perspectives on how to approach common programming tasks.

While I'm a fan of TypeScript Enums for the type safety they provide, your article makes some valid points about alternative ways to handle certain situations. It's crucial for developers to be aware of different approaches and choose the one that best fits the specific needs of their project.

What I appreciate most about your post is that it encourages a healthy discussion about TypeScript's strengths and potential alternatives, which can help us all become better developers. Thanks for sharing your insights and sparking this conversation!

I believe the best approach often depends on the context of the project and the development team's preferences. Keep the great articles coming, and I'm looking forward to more thought-provoking discussions in the future!

Collapse
 
maafaishal profile image
Muhammad A Faishal

Yeah, it does. Sometimes speed is prioritized over performance in a project...

Anyway, thanks for the kind feedback!

Collapse
 
atinypixel profile image
Aziz Kaukawala

Seems introspective! Gonna try this approach!
Thanks Muhammad!

Collapse
 
maafaishal profile image
Muhammad A Faishal

Cool!

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
maafaishal profile image
Muhammad A Faishal

We use as const since it can infer the property values following typescriptlang.org/docs/handbook/e....

Speaking of Object.freeze, I've tried it and the result is it couldn't infer the property values. Maybe, can you give the example?

Collapse
 
mmvergara profile image
mmvergara • Edited

oh it doesn't infer?, im sorry didn't knew I was just guessing.

Thread Thread
 
maafaishal profile image
Muhammad A Faishal

No, it doesn't...

Collapse
 
sergeyshandar profile image
Sergey Shandar

I'm avoiding TypeScript enums with all cost. I prefer to use unions instead

type Color = 'RED' | 'GREEN' | 'BLUE';
Enter fullscreen mode Exit fullscreen mode

This way, TypeScript doesn't need to generate extra hidden code. Unions are also compatible with JavaScript type annotations proposal but enums are not.

Collapse
 
maafaishal profile image
Muhammad A Faishal • Edited

Yeah, ultimately, the best approach is to go back to the basics.

Anyway, wow JS will be able to accept type annotations by itself. It's great news!

Collapse
 
ismaelguerrib profile image
Ismaël Guerrib

Thanks Muhammad for this nice explanations !

Using TypeORM in a CRUD app builder, do you think that this preference for const over enum should also apply to databases or the concept of Enum is getting to the developer precious documentation in his development experience which can not really be mesurable ?

It really gives me food for thought !

Collapse
 
maafaishal profile image
Muhammad A Faishal

Personally, I've never tried TypeORM and CASE. But, if it needs to transpile the source code, I suggest you to replace Enum. Otherwise, using Enum is not a problem.

Anyway, you can do you own research on the execution time to check whether Enum can increase the execution time or not.

Collapse
 
calinzbaenen profile image
Calin Baenen

What does the as const do? What if I were to remove it?

Collapse
 
maafaishal profile image
Muhammad A Faishal

Here is the difference

Image description

Collapse
 
smoni profile image
SMoni

Nice article... I've created a small snippet to create an enum only by the provided strings

stackblitz.com/edit/js-kngxa2?file...

Collapse
 
maafaishal profile image
Muhammad A Faishal

Yeah, it can be an option for someone who is lazy enough to define the object with as const. My feedback is don't forget to support TypeScript.

By the way, it's good!.

Collapse
 
dangduytung profile image
dangduytung

With TypeScript, It looks like simple expression and to understand easily

Collapse
 
maafaishal profile image
Muhammad A Faishal

Yeah, it does

Collapse
 
xyangst profile image
Angst

did you forget number enums? not having to provide a index is a huge bonus imo, also calling a function with a string isnt really easy to refactor later on