Enum is an entity that helps to better structure similar items. This language structure allows you to create a set of names and then refer to them. Enums were created to limit the number of values we can work with in a particular variable. The most common use case for enumerations is storing different statuses. But there are other cases as well. For example, they are used for storing unchanging data like weekdays, months, moving directions, etc. In this topic, you will see how enums work and learn to use them to your advantage.
Creating an enum
Let's create an enum and see how we can work with it.
enum Direction {
Up,
Down,
Left,
Right
}
Enum is declared by the enum keyword, followed by the enum's name and a set of enum members (constants). By default, enum members have numeric values starting from 0:
console.log(Direction.Up); //Output: 0
console.log(Direction.Left); //Output: 2
When you set the first value by yourself, the others are set automatically:
enum Direction {
Up = 10,
Down, // 11
Left, // 12
Right // 13
}
console.log(Direction[11]) //Output: Down
Also, we can give literal values to enum members:
enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
An enumeration is both a value and a type. It can be specified as a type in function parameters:
function move(direction: Direction, distance: number) {
console.log(`Move ${distance} units ${direction}.`)
}
move(Direction.Down, 3); //Output: Move 3 units DOWN.
move(Direction.Left, 5); //Output: Move 5 units LEFT.
move(Direction.UpRight, 5); //Error: Property 'UpRight' does not exist on type 'typeof Direction'.
By specifying the direction parameter with a type of Direction, you ensure that the function only accepts valid enum values and provides type checking benefits. If you try to pass an invalid value, TypeScript will generate a compilation error, helping catch potential bugs early in the development process.
Enums after compilation
Let's see how a TypeScript compiler transpiles enum to JavaScript code. Write your own enum, use the tsc command in your terminal to create a related JavaScript file, and compare the compiled result with your code.
When you compile TypeScript code with enums to JavaScript, the enum is transpiled into JavaScript code.
enum ArticleStatus {
InProcess,
Ready,
Published,
}
$ tsc filename
TypeScript generates an immediately-invoked function expression (IIFE) that defines the enum and its values.
var ArticleStatus;
(function (ArticleStatus) {
ArticleStatus[ArticleStatus["InProcess"] = 0] = "InProcess";
ArticleStatus[ArticleStatus["Ready"] = 1] = "Ready";
ArticleStatus[ArticleStatus["Published"] = 2] = "Published";
})(ArticleStatus || (ArticleStatus = {}));
The enum members are stored as properties on the ArticleStatus object. The enum values are assigned both numeric values and string values. The numeric values represent the index of the member, and the string values are the member names.
Reverse mappings
In the generated code above, an enum is compiled into an object that stores both forward (name → value) and reverse (value → name) mappings. This means that you can easily map from enum values to their corresponding enum names, and vice versa.
let state = ArticleStatus.Published; //2
let nameOfState = ArticleStatus[state] //Published
Be aware that there is no generation of a reverse mapping with string enum members.
Regular vs. const enum
Enumerations are suitable for many situations, but sometimes there are stricter requirements. To avoid the overhead of generating extra code and additional steps when accessing enum values, you may choose to use const enums. They are defined by adding const before the enum declaration:
const enum ArticleStatus {
InProcess,
Ready,
Published,
}
console.log(ArticleStatus.InProcess)
console.log(ArticleStatus.Ready)
console.log(ArticleStatus.Published)
After transpiling, the JavaScript code will have just values instead of an object.
console.log(0 /* ArticleStatus.InProcess */);
console.log(1 /* ArticleStatus.Ready */);
console.log(2 /* ArticleStatus.Published */);
const enum values are replaced with their literal values at compile time, while regular enums introduce runtime objects. So the code is completely virtual and is fully erased during compilation.
Conclusion
Here's what you should remember about enums:
- Enum is a fixed set of logically related constants whose values can be either numbers or strings.
- Number values implement reverse mappings.
- Enums declared via
const enumare completely removed during compilation. - Use enums to be sure that you operate only on valid enum values, reducing the risk of bugs, and store values inside an enum without cluttering the global code with constants.
To sum up, enums in TypeScript provide a mechanism for defining a set of named constant values. They offer several advantages, including improved code readability, type safety, and better tooling support. Enums help catch type-related errors at compile-time, enhancing code reliability and maintainability. They are particularly useful for representing fixed sets of related values, such as days of the week, statuses, or configuration options. However, it's essential to use enums wisely and consider alternatives like string literal types or union types when more flexibility is required. Overall, TypeScript enums are a powerful tool that contributes to more robust and self-documenting code in modern web development.