As a web developer, I’m constantly learning new ways to improve my coding practices. One of the more recent additions to my toolkit is TypeScript, a powerful superset of JavaScript that provides additional features to make coding easier and more efficient. One of my favorite features of TypeScript is enums, which allow me to better organize and define a collection of related values. In this article, I’ll dive deeper into TypeScript enums and show you how to use them effectively.
Introduction: What is TypeScript?
Before we dive into enums, let’s take a step back and talk about TypeScript itself. TypeScript is, as mentioned earlier, a superset of JavaScript. This means that it extends the functionality of the JavaScript language with additional features like classes, interfaces, and a static type system. TypeScript code is compiled into JavaScript, which means it can be used in any modern web browser or server environment.
At its core, TypeScript is designed to make writing JavaScript easier and more efficient. It provides tools to help catch errors early in the development process, and its typing system helps eliminate whole categories of bugs that are common in pure JavaScript. By using TypeScript, I can be more confident in the code that I write and more productive overall.
Defining Enums in TypeScript
Now that we’ve covered the basics of TypeScript, let’s move on to enums. An enum, short for enumeration, is a named collection of related values. In TypeScript, enums are defined using the enum
keyword and can be defined in both numeric and string formats.
Here’s an example of defining a simple numeric enum:
enum Color {
Red,
Green,
Blue
}
In this example, we’ve defined an enum called Color
that has three possible values: Red
, Green
, and Blue
. By default, each of these values is assigned an index starting at 0, so Red
has an index of 0, Green
has an index of 1, and so on.
Enums can also be defined with explicit index values, like this:
enum Color {
Red = 1,
Green = 2,
Blue = 4
}
In this example, we’ve assigned explicit values to each of the enums. This can be useful in cases where you want to be sure that the value of the enum always matches a specific number.
Enum Values
There are three main types of enums in TypeScript: numeric enums, string enums, and heterogeneous enums. Each of these types has different use cases and can be useful in different situations.
Numeric enums
Numeric enums are the simplest type of enum in TypeScript. As the name suggests, numeric enums use numbers as their values. Here’s an example:
enum Direction {
Up,
Down,
Left,
Right
}
In this example, we’ve defined an enum called Direction
that has four possible values: Up
, Down
, Left
, and Right
. By default, the Up
value has an index of 0, Down
has an index of 1, and so on.
Numeric enums can also be defined with explicit index values, like this:
enum Direction {
Up = 1,
Down,
Left,
Right
}
In this example, we’ve assigned an explicit value to the Up
enum, and the other enums are assigned automatically starting from there.
String enums
String enums are similar to numeric enums, but they use strings as their values instead of numbers. Here’s an example:
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT"
}
In this example, we’ve defined an enum called Direction
that has four possible values: UP
, DOWN
, LEFT
, and RIGHT
.
String enums can be useful in cases where you want the value of the enum to be more descriptive. For example, you might use a string enum to represent different types of user roles or task states.
Heterogeneous enums
Heterogeneous enums are enums that have values of different types. Here’s an example:
enum Status {
Pending = 1,
Approved = "APPROVED",
Rejected = { reason: "INVALID", code: 400 }
}
In this example, we’ve defined an enum called Status
that has three possible values: Pending
, Approved
, and Rejected
. The value of Pending
is assigned the number 1, the value of Approved
is a string, and the value of Rejected
is an object.
Heterogeneous enums can be useful in cases where you want to store additional information along with the enum value.
Enum Methods
Now that we’ve covered the basics of defining enums, let’s talk about some of the methods that are available to use with enums in TypeScript.
The keyof operator
One useful method that you can use with enums in TypeScript is the keyof
operator. This operator allows you to get a list of all the keys in an enum. Here’s an example:
enum Color {
Red,
Green,
Blue
}
type ColorKeys = keyof typeof Color; // "Red" | "Green" | "Blue"
In this example, we’ve defined an enum called Color
and used the keyof
operator to get a list of all its keys. As you can see, the ColorKeys
type ends up being a union of all the possible key names. This can be useful in cases where you want to iterate over all the possible values of an enum.
The for…in loop
Another useful method for working with enums is the for...in
loop. This loop allows you to iterate over all the values in an enum and perform some action with each one.
enum Color {
Red,
Green,
Blue
}
for (let key in Color) {
console.log(key); // outputs "Red", "Green", "Blue", and potentially more
}
In this example, we’re using a for...in
loop to iterate over all the values in the Color
enum and log them to the console. One thing to note is that the for...in
loop can also iterate over any additional properties that might be defined on the enum. So if you have an enum with an additional property like this:
enum Color {
Red,
Green,
Blue
}
Color.Black = "#000000";
for (let key in Color) {
console.log(key); // outputs "Red", "Green", "Blue", and "Black"
}
The for...in
loop will also iterate over the Black
property, even though it’s not technically an enum value.
Casting enums to other types
Finally, you can also use enums in conjunction with other TypeScript types by casting them to other types. Here’s an example:
enum Animal {
Cat,
Dog,
Fish
}
interface Cat {
type: Animal.Cat;
name: string;
}
let myCat: Cat = { type: Animal.Cat, name: "Fluffy" };
In this example, we’re defining an interface for a Cat
object, which includes a type
property that is set to the Cat
value of the Animal
enum. We then create a new myCat
object and set its type
property to Animal.Cat
.
Using Enums in TypeScript
Now that we’ve covered the basics of defining and working with enums in TypeScript, let’s talk about some of the ways that you can use enums in your actual TypeScript code.
Enum as function parameters
One common use case for enums is to use them as parameters for functions. For example, let’s say that we have a function that needs to know whether to sort a list of items in ascending or descending order. We could define an Order
enum like this:
enum Order {
Ascending,
Descending
}
function sortItems(order: Order) {
if (order === Order.Ascending) {
// sort items in ascending order
} else {
// sort items in descending order
}
}
In this example, we’re defining an Order
enum with two values: Ascending
and Descending
. We then define a function called sortItems
that takes an Order
value as its parameter. Inside the function, we check to see whether the value is set to Ascending
or Descending
and sort the items accordingly.
Switch statements with enums
Another common use case for enums is to use them in switch statements. This can be useful in cases where you need to perform different actions based on the value of an enum. Here’s an example:
enum Color {
Red,
Green,
Blue
}
function getColorName(color: Color) {
switch (color) {
case Color.Red:
return "red";
case Color.Green:
return "green";
case Color.Blue:
return "blue";
}
}
In this example, we’re defining an enum
called Color
with three possible values. We then define a function called getColorName
that takes a color
parameter of type Color
. Inside the function, we use a switch
statement to check the value of the color
parameter and return a string representing the color name if it matches one of the enum values.
Enums for constants
Enums can also be used to define constants in your TypeScript code. For example, let’s say that we have a maximum number of items that a user can add to their cart. We can define this maximum using an enum like this:
enum Cart {
MaxItems = 10
}
In this example, we’re defining an enum called Cart
with a single constant MaxItems
that is set to 10. We can then use this enum in our code to enforce the maximum number of items that a user can add to their cart.
Conclusion
Enums are a powerful feature of TypeScript that allow developers to better define and organize related values. By using enums, you can improve the readability and maintainability of your code, and make it easier to catch errors early in the development process. Whether you’re using enums as function parameters, constants, or just to make your code more readable, they are a valuable tool that every TypeScript developer should be familiar with.
Learn Typescript Modules: Organization & Reusability
As a developer, I am always looking for ways to make my code more organized and efficient. One tool that has helped me achieve this goal is Typescript modules. In this article, I will be discussing Typescript modules in-depth, including how to create and import them, how to declare dependencies, and the benefits of using […]
Mastering Typescript Decorators
As a software developer, I am constantly looking for ways to improve the efficiency and effectiveness of my work. One of the most powerful tools in my arsenal has been typescript decorators. In this article, I will dive deep into the world of typescript decorators, exploring their history, various types, and usage in software development. […]
Typescript Utility Types
Introduction Hi there, I’m excited to talk to you today about Typescript Utility Types. First, let’s provide a brief overview of what Typescript is for those who may not be familiar with it. Typescript is an open-source programming language that builds on top of JavaScript by adding static types to code. This can help catch […]
Typescript Namespaces: Best Practices
As a software developer, I have been intrigued by TypeScript’s ability to introduce new features to the JavaScript language while also minimizing the potential for runtime errors. One of the best things about TypeScript is that it provides excellent support for large codebases, and one of the features that can help with this is Namespaces. […]
Learning Typescript Iterators
Introduction As a software developer who is always looking for efficient ways to write clean code, I discovered Typescript and the concept of iterators. Typescript is a JavaScript superset that enables the creation of more structured and maintainable code. In this article, I am introducing Typescript iterators and delving into their different types, how to […]
Typescript Declaration Merging
Introduction Typescript Declaration Merging is an essential feature of the Typescript language, which allows developers to extend existing code without modifying it. It can be a bit complex and overwhelming for beginners, but once you understand how it works, you’ll find it to be a powerful tool. As a developer, you will come across scenarios […]