Altcademy - a Forbes magazine logo Best Coding Bootcamp 2023

What are Enums in JavaScript?

Enums, short for enumerations, are a powerful feature in many programming languages. They allow us to define a collection of named values, representing distinct elements of a set. Unfortunately, JavaScript does not have built-in support for enums, but we can still create them using objects and several other techniques.

In this blog post, we will explore enums in JavaScript, understand their purpose and benefits, and learn how to implement them using various approaches. We will also provide plenty of code examples and analogies to help you grasp the concepts more easily.

Why Use Enums in JavaScript?

Imagine you are building a weather app, and you need to represent different weather conditions like "sunny", "cloudy", "rainy", and "snowy". You could use strings to represent these conditions, but strings come with a few drawbacks:

  1. They are prone to typos, which can lead to bugs.
  2. They do not provide any context, making it harder for other developers to understand their purpose.
  3. They are not easily refactorable; if you want to change the name of a value, you need to search and replace it throughout the entire codebase.

Enums solve these problems by providing a single place to define and manage all possible values. Enums also make your code more readable and maintainable, as they provide a clear and self-documenting way to represent sets of distinct values.

Implementing Enums Using Plain Objects

The most straightforward way to create an enum in JavaScript is to use an object. Here's an example of an enum representing the aforementioned weather conditions:

const Weather = {
  SUNNY: 'sunny',
  CLOUDY: 'cloudy',
  RAINY: 'rainy',
  SNOWY: 'snowy',
};

Now, instead of using raw strings, we can use the Weather enum to represent weather conditions:

const currentWeather = Weather.SUNNY;

if (currentWeather === Weather.SUNNY) {
  console.log('It is sunny outside!');
}

This approach is simple and works well for most use cases, but it has a few drawbacks:

  1. The values of the enum are still strings, which can be accidentally changed or overridden.
  2. The enum is mutable, meaning that new values can be added, and existing ones can be modified or deleted.

Implementing Enums Using Object.freeze()

To make our enums more robust, we can use the Object.freeze() method to create an immutable object. This method prevents any changes to the object, ensuring that our enum values remain constant and cannot be modified accidentally.

const Weather = Object.freeze({
  SUNNY: 'sunny',
  CLOUDY: 'cloudy',
  RAINY: 'rainy',
  SNOWY: 'snowy',
});

Now, any attempt to change or delete a value from the Weather enum will result in an error:

Weather.SUNNY = 'rainy'; // Error: Cannot assign to read-only property 'SUNNY' of object '#<Object>'
delete Weather.SUNNY; // Error: Cannot delete property 'SUNNY' of object '#<Object>'

This makes our enums more reliable and less prone to bugs.

Implementing Enums Using TypeScript

TypeScript, a popular superset of JavaScript, provides built-in support for enums. If you are using TypeScript in your project, you can simply use the enum keyword to create an enum:

enum Weather {
  SUNNY,
  CLOUDY,
  RAINY,
  SNOWY,
}

By default, TypeScript assigns numeric values to the enum members, starting from 0. In the example above, Weather.SUNNY would have the value 0, Weather.CLOUDY would have the value 1, and so on.

You can also explicitly set the value of each enum member, either with a numeric or a string value:

enum Weather {
  SUNNY = 'sunny',
  CLOUDY = 'cloudy',
  RAINY = 'rainy',
  SNOWY = 'snowy',
}

TypeScript enums are powerful and offer additional benefits, such as type-checking and autocompletion in supported editors.

Enums in Practice: A Real-World Example

Now that we know how to create enums in JavaScript, let's take a look at a real-world example. Imagine we are building a messaging app, and we need to represent the status of each message: "sent", "delivered", "read", or "failed".

First, let's create an enum for the message status:

const MessageStatus = Object.freeze({
  SENT: 'sent',
  DELIVERED: 'delivered',
  READ: 'read',
  FAILED: 'failed',
});

Now, we can use the MessageStatus enum to represent the status of our messages:

const message = {
  text: 'Hello, world!',
  status: MessageStatus.SENT,
};

if (message.status === MessageStatus.SENT) {
  console.log('The message has been sent!');
}

By using enums, our code is more readable, maintainable, and less prone to errors.

Conclusion

Enums are a valuable tool for representing sets of distinct values in JavaScript. Although JavaScript does not have native support for enums, we can still create them using objects, Object.freeze(), or TypeScript.

By using enums in your code, you can improve readability, maintainability, and reduce the likelihood of bugs related to typos or incorrect values. So, the next time you find yourself juggling multiple strings or numbers representing different states, consider using enums to make your code more