December 6, 2023

Enums in TypeScript

What is an enum?

An enum is a way to give more friendly names to sets of values. Enums are a feature of TypeScript and are not available in JavaScript. Enums are not a new concept and are available in many other programming languages.

A quote from Wikipedia:

An enum is a data type consisting of a set of named values called elements, members, enumeral, or enumerators of the type. The enumerator names are usually identifiers that behave as constants in the language

Enum example

enum Color {
    Red,
    Green,
    Blue
}

This can be used like this:

const color: Color = Color.Green;

if (color === Color.Green) {
    console.log('The color is green');
}

This makes the code more readable and easier to understand.

Different types of enums

There are two different types of enums in TypeScript: numeric and string enums.

Numeric enums

Numeric enums are the default type of enums in TypeScript. The values of the enum members are numbers. The first member is 0, the second is 1 and so on.

enum Color {
    Red,
    Green,
    Blue
}

console.log(Color.Red); // 0
console.log(Color.Green); // 1
console.log(Color.Blue); // 2

But you can also set the values of the enum members manually:

enum Color {
    Red = 100,
    Green = 200,
    Blue = 300
}

console.log(Color.Red); // 100
console.log(Color.Green); // 200
console.log(Color.Blue); // 300

String enums

String enums are enums where the values of the enum members are strings. String enums are useful when you need to have a human-readable value for the enum members. Also to avoid hard coding strings in your code that are used in multiple places.

enum Status {
    Active = 'active',
    Inactive = 'inactive',
    Pending = 'pending'
}

Instead of hard coding the string values in your code you can now use the enum members:

const status: Status = Status.Active;

if (status === Status.Active) {
    console.log('The status is active');
}

Once again makes the code more readable and easier to understand.

Enum as types

You can also use enums as types. This is useful when you want to be more specific about the values that can be used. Instead of using a string as type and limit the values with union types you can use enums to make it more readable and less error prone.

enum Status {
    Active = 'active',
    Inactive = 'inactive',
    Pending = 'pending'
}

const setStatus = (status: Status) => {
    // ...
}

setStatus(Status.Active);
setStatus(Status.Inactive);
setStatus(Status.Pending);

Using enums as types in interfaces

enum Status {
    Active = 'active',
    Inactive = 'inactive',
    Pending = 'pending'
}

interface User {
    id: number;
    name: string;
    status: Status;
}

const user: User = {
    id: 1,
    name: 'John Doe',
    status: Status.Active
}

Create other types by iterating enums

One recent use case I had for using enums as types was to create a map type from an enum.

enum Status {
    Active = 'active',
    Inactive = 'inactive',
    Pending = 'pending'
}

type StatusAction = {
    [key in Status]: {
        title: string;
        onClick: () => void;
    }[]
}

const actions: StatusAction = {
    [Status.Active]: [
      {
        title: "Edit",
        onClick: () => {
          console.log("Edit clicked");
        },
      },
      {
        title: "Remove",
        onClick: () => {
          console.log("Remove clicked");
        },
      },
    ],
    [Status.Inactive]: [
      {
        title: "Edit",
        onClick: () => {
          console.log("Edit clicked");
        },
      },
      {
        title: "Acivate",
        onClick: () => {
          console.log("Set active");
        },
      },
    ],

    [Status.Pending]: [
      {
        title: "Edit",
        onClick: () => {
          console.log("Edit clicked");
        },
      },
      {
        title: "Acivate",
        onClick: () => {
          console.log("Set active");
        },
      },
    ],
  };

This lets you iterate over each value in the enum and set unique actions or values for each enum member. I used this to create actions in a data table where each row had a status that needed specific actions tied to it.

const status = Status.Active;

{actions[status].map((action) => (
    <button onClick={onClick}>{action.title}</button>
)}

This post has just scratched the surface of what enums are and how they can be used in TypeScript.

Thank you for reading this far! 🎉

Follow me on Twitter for more inspiration and dev tips.

Feel free to reach out if you have any feedback or questions.

Check out the blog page for more articles.