How to Create and Use Enums in TypeScript: A Beginner's Guide

Enums, short for enumerations, are a special kind of data type that allow you to group related values together. This feature is particularly useful when you want to define a set of named constants, making your code easier to read and understand. While JavaScript doesn’t natively support enums, TypeScript, a typed superset of JavaScript, brings this useful feature to the table.

In this blog post, we will cover:

  1. What are Enums?
  2. How to Create Enums in TypeScript.
  3. Const Enums.
  4. Accessing Enums.
  5. Enum Methods.
  6. Using Enums in Functions.
  7. Enum as Function Parameters.
  8. String Enums.

What are Enums?

Enums are a way to group related constants together under a single name. For example, let’s say you’re building a weather app and you need to categorize different types of weather conditions. Rather than using arbitrary strings like “Sunny”, “Rainy”, “Cloudy”, you can create an enum to hold these values. This makes the code more manageable and less error-prone.

How to Create Enums in TypeScript

Creating an enum in TypeScript is quite straightforward. Use the enum keyword followed by the name of the enum and a set of curly braces containing the enum values.

Here’s a simple example:

enum Weather {
  Sunny,
  Rainy,
  Cloudy,
  Snowy
}

By default, the first member will get the value 0, the second member 1, and so on. However, you can manually set the value of the enum members if needed:

enum Weather {
  Sunny = 1,
  Rainy = 2,
  Cloudy = 3,
  Snowy = 4
}

You can also use strings for enum values:

enum Weather {
  Sunny = "SUNNY",
  Rainy = "RAINY",
  Cloudy = "CLOUDY",
  Snowy = "SNOWY"
}

Const Enums

If an enum does not require computed members, you can make it a const enum. This will completely remove the enum from the generated JavaScript code.

const enum Directions {
  Up,
  Down,
  Left,
  Right
}

let dir = Directions.Up; // translates to let dir = 0; in JavaScript

Accessing Enums

Accessing enum values is simple. You use the enum name followed by the dot operator and the enum member name.

let currentWeather: Weather = Weather.Sunny;

You can also access the enum value’s corresponding string name using the enum and square brackets:

let weatherName: string = Weather[currentWeather];
console.log(weatherName);  // Output will be "Sunny" if `currentWeather` is `Weather.Sunny`.

Enum Methods

Enums in TypeScript don’t have built-in methods, but you can use regular JavaScript methods to achieve various functionalities.

For example, to iterate through all enum members, you can use a for...in loop.

for (let weather in Weather) {
  if (isNaN(Number(weather))) {
    console.log(weather);  // Outputs: "Sunny", "Rainy", "Cloudy", "Snowy"
  }
}

Using Enums in Functions

When you define an enum, you create a distinct type. This allows you to use the enum type as a parameter type in functions. When using enums in functions, you can leverage TypeScript’s type checking to make sure you’re only dealing with valid enum values. Here’s an extended example:

enum Role {
  Admin,
  User,
  Guest
}

function describeRole(role: Role) {
  switch (role) {
    case Role.Admin:
      console.log("You have full access.");
      break;
    case Role.User:
      console.log("You have limited access.");
      break;
    case Role.Guest:
      console.log("You have guest access.");
      break;
    default:
      console.log("Invalid role.");
  }
}

// Usage
describeRole(Role.Admin);  // Output: 'You have full access.'
describeRole(Role.User);   // Output: 'You have limited access.'
describeRole(Role.Guest);  // Output: 'You have guest access.'

As you can see, using enums in functions can simplify the logic by making the code more readable and maintainable.

Enum as Function Parameters

Using enums as function parameters adds an extra layer of type safety. It ensures that the function only accepts predefined values, thus reducing the risk of errors. If you try to pass a value that isn’t part of the enum, TypeScript will throw a compilation error.

enum PaymentStatus {
  Paid,
  Unpaid,
  Pending
}

function setPaymentStatus(status: PaymentStatus) {
  // Implementation
}

setPaymentStatus(PaymentStatus.Paid);   // Valid
setPaymentStatus(PaymentStatus.Unpaid); // Valid
setPaymentStatus(3);                     // Compilation Error

In the above example, attempting to call setPaymentStatus(3) will result in a compilation error, thus helping to catch mistakes early in the development process.

String Enums

In TypeScript, you have the option to use string enums, which makes the code easier to read and debug. Unlike numeric enums, the values of string enums are initialized with string literals rather than auto-incremented numbers.

enum TrafficLight {
  Red = "RED",
  Yellow = "YELLOW",
  Green = "GREEN"
}

function describeTrafficLight(light: TrafficLight) {
  if (light === TrafficLight.Red) {
    console.log("Stop!");
  } else if (light === TrafficLight.Yellow) {
    console.log("Get Ready!");
  } else if (light === TrafficLight.Green) {
    console.log("Go!");
  }
}

describeTrafficLight(TrafficLight.Red); // Output: 'Stop!'

One major advantage of string enums is that they provide better readability when debugging. If you debug a program and inspect a variable holding an enum value, a string enum will show the human-readable string instead of a numeric value.

Conclusion

Enums in TypeScript offer a convenient way to group related constants, making your code easier to read and maintain. They are particularly helpful in large applications where the same set of constant values may be used in multiple places. With TypeScript enums, you can avoid magic numbers and strings, resulting in cleaner and more maintainable code.