TypeScript Enum Tutorial – How to Use Enum in TypeScript

By Sruthy

By Sruthy

Sruthy, with her 10+ years of experience, is a dynamic professional who seamlessly blends her creative soul with technical prowess. With a Technical Degree in Graphics Design and Communications and a Bachelor’s Degree in Electronics and Communication, she brings a unique combination of artistic flair…

Learn about our editorial policies.
Updated March 9, 2024

In this tutorial, we’ll be going over the TypeScript Enum by looking at code examples explaining how to use enums in TypeScript:

What is an enum?

Enum is short for enumeration. An enum is a special data type that allows you to define a group or a set of predefined constants.

For example, if I wanted to represent the four models of cars in a showroom, I can define an enum with the name Model. Inside it, we can have a list of all the different car models available for purchase like Toyota, Audi, Mercedes, and Peugeot.

=> Explore The Simple TypeScript Training Series Here

TypeScript Enum

Enums In TypeScript1

enum Model {

Toyota,
Audi,
Mercedes,
Peugeot
}

This is how you define an enum. You begin by stating the enum keyword, and then you have the name of your enum, then inside the curly braces, you list all of your predefined constants.

Why are Enums Useful?

Well, enums allow us to have named constants. Using named constants allows us i.e. the programmers – to better document our intent i.e. what we want our program to do.

Enums with Functions

Let’s say we have a simple function printCars, and it’s simply going to take in a car and print it out.

But let’s say we’re not going to use enums for this. How do we do this? We have to figure out a way to represent each car.

Here, what we can do is we can use integers. We could say zero represents Toyotas, one for Audis, two for Mercedes, and three for Peugeots. Let’s do that.

Let’s pass in our car, which is going to be of type number. Now we have to get a switch statement that’s going to figure out which car this is.

enum Model {

Toyota,
Audi,
Mercedes,
Peugeot
}

function printCars(car: number) {
switch(car) {
case 0:
console.log("Toyota")
break
case 1:
console.log("Audi")
break
case 2:
console.log("Mercedes")
break
case 3:
console.log("Peugeot")
break
}
printCars(0)
}

Let’s say switch car in case zero, we’re going to console log Toyota, break case one, console log Audi, break case two, console log Mercedes break case three and lastly console log Peugeot.

If we want to test this out, we could say print car zero, and then we’d run it over and get Toyota. Or if we wanted to pass in, say, three, we’d run this again and we’d get Peugeot.

This works. But this function could be a lot clearer about what it’s trying to do. It takes in any number.

We could pass in 99 or negative six, and our program would run, but it would break. Yes, we can go through the cases and see that. Case zero is Toyota, Case one is Audi, Case two is Mercedes, and three is Peugeot.

But this is just an example program. Theoretically, these cases could be dozens of lines long, and you might have to go and search through these case statements one by one to actually remember which cars represent which case.

This is an all-right solution. But we could do a lot better. Let’s try this again. But this time using enums. So, we’re going to delete the switch.

The Same Program Using Typescript Enum

If we wanted to try this using enums, we need to swap this number, type out and make the car a type of Model.

Let’s switch cars, let’s say the case, then console log Toyota, break. Case car Audi, break. Case car Mercedes, console log Mercedes, break. Peugeot console log break. This is a little bit better.

function printCars(car: Model) {
switch(car) {
case Model.Toyota:
console.log("Toyota")
break
case Model.Audi:
console.log("Audi")
break
case Model.Mercedes:
console.log("Mercedes")
break
case Model.Peugeot:
console.log("Peugeot")
break
}
printCars(Model.Mercedes)
}

When we try to call the method printCars(Model.Toyota). Let’s run it, we’ll get Toyota. If we wanted to pass in Model.Mercedes, we get Mercedes.

This is a lot better. It’s a lot clearer as to what each case represents. By using Typescript enum, we can define a set of predefined named constants that we can use to represent real-world things and make our program a lot clearer.

Enums by default Represent Real Numbers

Enums by default represent real numbers starting from zero and working their way up from there. When we hover over Toyota, this translates to zero – if you look at the intellisence as shown in the image below.

Enum index

Audi represents one, Mercedes two, and Peugeot three. If you don’t give any of your enum values, it’s going to be default zero, and it’s going to increment one from there and it’s going to keep going and going and going.

We can define our own values for these, I could give Toyota a value of four. If I were to leave these other ones blank, Audi would look at the enum number for Toyota and increment its value by one.

enum Model {

Toyota = 4,
Audi,
Mercedes,
Peugeot
}

So Audi would have a value of five, Mercedes would be six, and Peugeot would be seven as shown in the image below.

enum member

We could just give Audi any value that I want as well. Audi can be 100. Mercedes could be three. Peugeot can be twelve. You can give any value, any integer value to your enums.

enum Model {

Toyota = 4,
Audi = 100,
Mercedes = 3,
Peugeot = 12
}

You could even have string enums. Instead of four, if you want, you could give it the value of Toyota. Yes, you can do that.

enum Model {

Toyota = "TOYOTA",
Audi = "AUDI",
Mercedes = "MERCEDES",
Peugeot = "PEUGEOT"
}

Audi could be Audi. Mercedes could be Mercedes, and Peugeot could be Peugeot.

enum Model {

Toyota = "TOYOTA",
Audi = "AUDI",
Mercedes = "MERCEDES",
Peugeot = "PEUGEOT"
}

function printCars(car: Model) {
switch(car) {
case Model.Toyota:
console.log("Toyota")
break
case Model.Audi:
console.log("Audi")
break
case Model.Mercedes:
console.log("Mercedes")
break
case Model.Peugeot:
console.log("Peugeot")
break
}
}
printCars(Model.Mercedes)

The expected output of our complete code above is shown in the image below.

code

Let’s Look at another example

We have our object named annotations. It’s an object with three properties or keys. We have the annotation BeforeTest with the value zero, then Test with the value one, and afterTest with the value two.

const annotations = {
beforeTest: 0,
Test: 1,
afterTest: 2,
};

console.log(annotations.Test);

We can now use it across our whole application. For example, we can console log annotations.Test and we can easily comprehend what it’s all about. The actual value represented is one. We can try to write the same code using enumerables.

This is why I will comment everything out and create an enum, this is the reserved word to create enumerable.

We normally start enumerables with uppercase, the same case applies to Interfaces too. We’re actually creating an object and inside we have keys and values in the same way as in normal objects.

// const annotations = {
// beforeTest: 0,
// Test: 1,
// afterTest: 2,
// };

// console.log(annotations.Test);

enum Annotation {
BeforeTest,
Test,
AfterTest,
}

console.log(Annotation.Test);

We can start the enums properties with lowercase but uppercase is a common style. Let’s put a comma and then Test and the last one will be afterTest. The only difference is that there is a capital letter and we didn’t set values.

Let’s check in the console log to see what it will look like. We can write Annotation.Test. Let’s console log it. As you can see in the image below, we’re getting the same one as with the indented code.

Unindent the code and you can see it as shown on the image below as we are getting one and one. The result is exactly the same. We created enumerable Annotation, and inside we have three properties.

Three Properties

This works exactly like a plain object where these are keys, beforeTest, Test, and afterTest. The values start from zero and then from one and two. We can write Annotation.Test and get one.

Does the question arise as to what is the benefit of using enums if we can write a simple object? The main point is that we use it as a value thus Annotation dot something. But we can also use it as a data type, this is the main benefit.

enum Annotation {
BeforeTest,
Test,
AfterTest,
}

const beforeTestAnnotation: Annotation = Annotation.BeforeTest;

console.log(Annotation.Test);

We can create one property beforeTest Annotation. We can say that this is of type Annotation and we’re using our annotation.BeforeTest.

As you can see from the code above, we can use Annotation both as a data type and as a value. We have our beforeTest Annotation of type Annotation as shown in the image below, which means we will change it from const to let.

Since we used let we can now change it, we can write beforeTest Annotation and assign something. But the interesting thing is that we can’t assign a string because type foo is not assignable to type Annotation. That’s why we have an error as shown in the image below.

Error

In fact, our enum is a data type, and now we can assign only our annotations. In this case, we can write Annotation.AfterTest as shown in the code below and we don’t get an error.

const annotations = {
beforeTest: 0,
Test: 1,
afterTest: 2,
};

console.log(annotations.Test);

enum Annotation {
BeforeTest,
Test,
AfterTest,
}

let beforeTestAnnotation: Annotation = Annotation.BeforeTest;

beforeTestAnnotation = Annotation.AfterTest;

console.log(Annotation.Test);

This is really nice because in our case with annotations being just an object, we can’t really validate data types and we can’t assign something else there. We can only assign these available annotations.

By default, as we have seen, enums have values like zero, one and two, and so on but it’s not comfortable thus normally programmers tend to work with strings.

Just because we can put some data inside a string that we can read like numbers doesn’t make any sense. This is why we can assign values in the same way we are doing in an object.

The main difference is that we are NOT using a colon – this is the most common mistake that people make – instead we use an equal sign.

enum Annotation {
BeforeTest = “beforeTest”,
Test = "test",
AfterTest = "afterTest"
}

We can assign a string beforeTest, Test, and lastly afterTest. This is how we can assign values to our Annotation. Let’s reload the page, we’re not getting one instead, we’re getting string Test as shown on the image below.

running - Output

Using TypeScript Enum Inside Interfaces

Mostly, people use enums with strings. Also, it is really common to use enums in sign interfaces. For example, let’s create an interface for a Module.

Inside the Module we have id which is a string and we also have Annotation. Let’s specify that this Annotation is of the enum type. Inside this Annotation inside the Module block, we can only provide our enum and nothing else meaning we are on the safe side.

const annotations = {
beforeTest: 0,
Test: 1,
afterTest: 2,
};

console.log(annotations.Test);

enum Annotation {
BeforeTest = "beforeTest",
Test = "test",
AfterTest = "afterTest"
}

interface Module {
id: string
Annotation: Annotation;
}

let beforeTestAnnotation: Annotation = Annotation.BeforeTest;

beforeTestAnnotation = Annotation.AfterTest;

console.log(Annotation.Test);

This is why I highly recommend you to use enums for all constants in your application.

Enums Prefix or Postfix

It is a nice practice to prefix or postfix your enums. In our previous code we can’t tell what an Annotation is – is it an enum, an interface, or a class?

Let’s change our enum to AnnotationEnum, then inside the interface block, we can change it to AnnotationEnum, etc as shown below. It’s now clear that this is an enum, it’s not an interface and it’s not a class.

I highly recommend you do the same for all your entities for your current as well as future projects.

interface Module {
id: string
Annotation: AnnotationEnum;
}

Enums are a very important part of TypeScript – what we’ve covered is all you need to know as far as enums are concerned.

const annotations = {
beforeTest: 0,
Test: 1,
afterTest: 2,
};

console.log(annotations.Test);

enum AnnotationEnum {
BeforeTest = "beforeTest",
Test = "Test",
AfterTest = "afterTest"
}

interface Module {
id: string
Annotation: AnnotationEnum;
}

let beforeTestAnnotation: AnnotationEnum = AnnotationEnum.BeforeTest;

beforeTestAnnotation = AnnotationEnum.AfterTest;

console.log(AnnotationEnum.Test);

The expected output of our complete code above is shown in the image below.

expected output

Conclusion

In this tutorial, we have looked at all the content concerning TypeScript Enum. It’s important to point out that both the examples we looked at giving us specific knowledge, so don’t skip them.

To summarize, we have learned that “An enum is a special data type that allows you to define a group or a set of predefined constants.” Enums allow us to have named constants which allows us to better document what we want our program to do. Constants make our code a lot clearer and cleaner.

Enums by default represent real numbers starting from zero and working their way up from there. We normally start innumerable with uppercase, and the same case applies to Interfaces too. The main benefit of using TypeScript enum is that we can also use them as a data type.

When assigning values to enums, we use a colon, not an equal sign. It’s good practice to use prefix and postfix when naming enums in TypeScript.

PREV Tutorial | NEXT Tutorial

Was this helpful?

Thanks for your feedback!

Leave a Comment