TypeScript Reference : Enums

TypeScript Reference : Enums

Enums are a powerful feature in TypeScript that allows you to define a set of named constants. They provide a way to represent a fixed set of values that can be used throughout your code.

Enums in TypeScript are similar to enums in other programming languages, such as C# and Java. They allow you to define a list of named values, which can then be used as a type in your code. You can think of enums as a way of creating named groups of related values.

One of the key benefits of using enums in TypeScript is that they provide a way to make your code more expressive and self-documenting. Instead of using arbitrary numbers or strings to represent specific values, you can use enum members to clearly communicate your intentions.

In this TypeScript reference guide, we will cover everything you need to know about enums in TypeScript. We will explain how to define and use enums, how to assign values to enum members, and how to leverage enums in your code to improve readability and maintainability.

If you are new to TypeScript or want to level up your knowledge of the language, this guide will provide you with a comprehensive overview of enums and their usage in TypeScript.

What are Enums?

An enum in TypeScript is a way to define a set of named constant values. Enums are useful when you have a fixed set of values that you want to represent in your code. They add clarity and readability to your code by giving meaningful names to these values.

Enums allow you to define a set of named constants, which can be used as values for variables, function parameters, or property values. They are a way to give names to a set of numeric values, making your code more expressive and self-documenting.

Here is an example of how an enum is defined in TypeScript:

enum Direction {

Up,

Down,

Left,

Right,

}

In this example, we define an enum called “Direction” with four possible values: “Up” (which has the value 0), “Down” (which has the value 1), “Left” (which has the value 2), and “Right” (which has the value 3). These values are assigned automatically by TypeScript. However, you can also explicitly assign values to the enum members if needed.

Enums can be used in a variety of ways in TypeScript. You can use them as the type for variable declarations:

let userDirection: Direction;

Enums can also be used as function parameter types:

function move(direction: Direction) {

// ...

}

Enums can also be used as property types in classes or interfaces:

interface Player {

name: string;

direction: Direction;

}

Enums can be very useful in scenarios where you have a limited set of possible values. They make your code more readable, maintainable, and less error-prone, as the TypeScript compiler will enforce that only valid enum values are used.

Declaring Enums

An enum (short for “enumeration”) is a way to define a set of named values. In TypeScript, enums allow you to define a set of possible values that a variable can take. This helps to make your code more readable and maintainable.

Syntax

To declare an enum in TypeScript, you use the enum keyword followed by the name of the enum and a set of values enclosed in curly braces:

enum Color {

Red,

Green,

Blue

}

In the example above, Color is the name of the enum, and Red, Green, and Blue are the possible values that a variable of type Color can take.

Value assignment

Value assignment

By default, enums in TypeScript assign numeric values to each member starting from 0 and incrementing by 1. That means, in the example above, Red has a value of 0, Green has a value of 1, and Blue has a value of 2.

However, you can also assign specific values to enum members by explicitly specifying their values. For example:

enum Color {

Red = 1,

Green = 2,

Blue = 4

}

In the example above, Red is assigned a value of 1, Green is assigned a value of 2, and Blue is assigned a value of 4. The values can be any valid TypeScript expression, such as numbers, strings, or other enums.

Using enums

Once you have declared an enum, you can use it to define variables in your TypeScript code. For example:

let color: Color = Color.Red;

console.log(color); // Output: 0

In the example above, the variable color is declared as type Color and is assigned the value Color.Red, which has a value of 0. The output of the console.log statement will be 0.

Enums can also be used in switch statements. For example:

let color: Color = Color.Blue;

switch (color) {

case Color.Red:

console.log("The color is red");

break;

case Color.Green:

console.log("The color is green");

break;

case Color.Blue:

console.log("The color is blue");

break;

}

In the example above, the switch statement checks the value of the color variable, and depending on the value, executes the corresponding case block. In this case, the output will be “The color is blue”.

Enum Values

An enum is a way to define a set of named constants in TypeScript. Each member of an enum has a value associated with it, which can be either a numeric or string value.

Numeric Enums

In TypeScript, enums by default are numeric enums. Numeric enums assign increasing numeric values starting from 0 to each member of the enum. We can also explicitly set the value of enum members. Let’s see an example:

“`typescript

enum Direction {

Up,

Down,

Left,

Right

}

// Values of Direction enum members

console.log(Direction.Up); // Output: 0

console.log(Direction.Down); // Output: 1

console.log(Direction.Left); // Output: 2

console.log(Direction.Right); // Output: 3

“`

In the above example, each member of the `Direction` enum is assigned a numeric value starting from 0. The value of `Direction.Up` is 0, `Direction.Down` is 1, `Direction.Left` is 2, and `Direction.Right` is 3.

String Enums

Starting from TypeScript 2.4, string enums were introduced. String enums are similar to numeric enums except that the values are initialized with string literals instead of numeric values. Let’s see an example:

“`typescript

enum Color {

Red = ‘RED’,

Green = ‘GREEN’,

Blue = ‘BLUE’

}

// Values of Color enum members

console.log(Color.Red); // Output: RED

console.log(Color.Green); // Output: GREEN

console.log(Color.Blue); // Output: BLUE

“`

In the above example, each member of the `Color` enum is assigned a string value. The value of `Color.Red` is ‘RED’, `Color.Green` is ‘GREEN’, and `Color.Blue` is ‘BLUE’.

We can assign any valid string value to the enum members. However, it is recommended to use upper case letters for enum member values as they are constants.

Computed Enums

Enums can also have computed or dynamic values. In some cases, the value of an enum member depends on the value of other enum members. To achieve this, we can use constant enum expressions. Let’s see an example:

“`typescript

enum Weekday {

Monday = 1,

Tuesday = Monday + 1,

Wednesday = Tuesday + 1,

Thursday = Wednesday + 1,

Friday = Thursday + 1,

Saturday = 6,

Sunday = 7

}

// Values of Weekday enum members

console.log(Weekday.Monday); // Output: 1

console.log(Weekday.Tuesday); // Output: 2

console.log(Weekday.Wednesday); // Output: 3

console.log(Weekday.Thursday); // Output: 4

console.log(Weekday.Friday); // Output: 5

console.log(Weekday.Saturday); // Output: 6

console.log(Weekday.Sunday); // Output: 7

“`

In the above example, we are using constant enum expressions to compute the values of `Weekday` enum members. The value of `Tuesday` is calculated by adding `Monday` value with 1, `Wednesday` is calculated by adding `Tuesday` value with 1, and so on.

Using Enum Values

Once an enum is defined, we can use its values to assign variables or define function parameters or return types. For example:

“`typescript

enum StatusCode {

Success = 200,

NotFound = 404,

ServerError = 500

}

function getStatusMessage(code: StatusCode): string {

switch (code) {

case StatusCode.Success:

return ‘Success’;

case StatusCode.NotFound:

return ‘Not Found’;

case StatusCode.ServerError:

return ‘Server Error’;

default:

return ‘Unknown’;

}

}

const status = StatusCode.Success;

const message = getStatusMessage(status);

console.log(message); // Output: Success

“`

In the above example, we have an `enum` called `StatusCode` that represents HTTP status codes. We have a function `getStatusMessage` that takes a `StatusCode` parameter and returns its corresponding message. We then use the values of the `StatusCode` enum to assign a variable `status` and call the `getStatusMessage` function.

Enums are a powerful tool in TypeScript that allows us to define a set of named constants. Enum members can have either numeric or string values associated with them. We can use enum values to assign variables, define function parameters, or return types.

Accessing Enum Values

Once you have defined an enum in TypeScript, you can access its values using dot notation. Enum values can be accessed in two ways: by name or by value.

Accessing Enum Values by Name

If you know the name of the enum value, you can access it by using the dot notation with the enum name followed by the value name. For example, let’s say we have the following enum:

enum Direction {

Up = "UP",

Down = "DOWN",

Left = "LEFT",

Right = "RIGHT"

}

To access the value of the ‘Up’ enum value, you can use:

Direction.Up

This will return the string “UP”, which is the value assigned to the ‘Up’ enum constant.

Accessing Enum Values by Value

If you have the value of an enum and want to find the corresponding name, you can use the index signature of the enum. The index signature allows you to access enum values by their assigned value. For example:

enum Direction {

Up = 1,

Down,

Left,

Right

}

function getDirectionName(value: number): string {

return Direction[value];

}

In this example, the function getDirectionName takes a number as an argument and returns the corresponding name of the enum value. For example, if you pass 1 as the argument, it will return the string “Up”.

Using this approach, you can access enum values dynamically, based on their assigned values.

String Enums

String enums in TypeScript are similar to numeric enums but use strings as their values instead of numbers. They provide a way to use descriptive string values in place of numeric values.

When defining a string enum, each member of the enum is assigned a string constant value. You can think of a string enum as a “map” of constant names to constant values.

Here is an example of a string enum:

“`typescript

enum Direction {

Up = “UP”,

Down = “DOWN”,

Left = “LEFT”,

Right = “RIGHT”,

}

“`

In the example above, the enum `Direction` has four members: `Up`, `Down`, `Left`, and `Right`. Each member is assigned a string constant value.

String enums can be used in the same way as numeric enums. You can access their values using dot notation:

“`typescript

console.log(Direction.Up); // Output: “UP”

console.log(Direction.Down); // Output: “DOWN”

“`

String enums can also be used in switch statements:

“`typescript

function move(direction: Direction) {

switch (direction) {

case Direction.Up:

console.log(“Moving up”);

break;

case Direction.Down:

console.log(“Moving down”);

break;

case Direction.Left:

console.log(“Moving left”);

break;

case Direction.Right:

console.log(“Moving right”);

break;

default:

console.log(“Invalid direction”);

break;

}

}

move(Direction.Right); // Output: “Moving right”

“`

String enums are useful when you want to represent a set of values that have a specific semantic meaning. They can improve the readability and maintainability of your code by using descriptive string values instead of arbitrary numbers.

Enum with Labels

An enum in TypeScript can also have labels associated with its values. This allows you to specify custom labels for each enum value, which can be useful for displaying the enum values in a user-friendly format, or for mapping the enum values to some other values.

To assign labels to enum values, you can use the following syntax:

enum Status {

Active = 'Active Status',

Inactive = 'Inactive Status',

Pending = 'Pending Status'

}

In the above example, each enum value is assigned a custom label as a string. You can use any valid string as a label.

When using an enum value, you can access its label using the dot notation:

console.log(Status.Active); // Output: "Active Status"

console.log(Status.Inactive); // Output: "Inactive Status"

console.log(Status.Pending); // Output: "Pending Status"

You can also use the enum values as keys in an object to map them to some other values:

const statusMapping = {

[Status.Active]: 'isActive',

[Status.Inactive]: 'isInactive',

[Status.Pending]: 'isPending'

};

console.log(statusMapping[Status.Active]); // Output: "isActive"

console.log(statusMapping[Status.Inactive]); // Output: "isInactive"

console.log(statusMapping[Status.Pending]); // Output: "isPending"

In the above example, each enum value is used as a key in the statusMapping object to map it to a different value. This can be useful for performing some kind of transformation or lookup based on the enum value.

Enums with labels can make your code more readable and maintainable by providing meaningful names for the enum values, and by allowing you to map the enum values to other values or manipulate them in some way.

Enum with Methods

Enums in TypeScript can also have methods, allowing you to define behavior for each enum value.

To add a method to an enum, you need to define a property and assign it a function.

Example:

“`typescript

enum Direction {

Up,

Down,

Left,

Right

}

enum Weekday {

Monday,

Tuesday,

Wednesday,

Thursday,

Friday,

Saturday,

Sunday

}

// Example method #1

Direction.prototype.inverse = function() {

if (this === Direction.Up) {

return Direction.Down;

} else if (this === Direction.Down) {

return Direction.Up;

} else if (this === Direction.Left) {

return Direction.Right;

} else if (this === Direction.Right) {

return Direction.Left;

}

}

// Example method #2

Weekday.prototype.sayHello = function() {

if (this === Weekday.Monday) {

return “Hello, it’s Monday!”;

} else if (this === Weekday.Tuesday) {

return “Hello, it’s Tuesday!”;

} else if (this === Weekday.Wednesday) {

return “Hello, it’s Wednesday!”;

} else if (this === Weekday.Thursday) {

return “Hello, it’s Thursday!”;

} else if (this === Weekday.Friday) {

return “Hello, it’s Friday!”;

} else if (this === Weekday.Saturday) {

return “Hello, it’s Saturday!”;

} else if (this === Weekday.Sunday) {

return “Hello, it’s Sunday!”;

}

}

// Usage

console.log(Direction.Up.inverse()); // Output: Down

console.log(Direction.Left.inverse()); // Output: Right

console.log(Weekday.Monday.sayHello()); // Output: Hello, it’s Monday!

console.log(Weekday.Friday.sayHello()); // Output: Hello, it’s Friday!

“`

In the above example, we define two enums: `Direction` and `Weekday`. We add methods to both enums using the `prototype` property. The `inverse` method of the `Direction` enum returns the opposite direction when called on a specific enum value. The `sayHello` method of the `Weekday` enum returns a greeting based on the enum value it is called on.

We can then call these methods on enum values just like we would call methods on objects. For example, `Direction.Up.inverse()` returns `Direction.Down`, and `Weekday.Monday.sayHello()` returns “Hello, it’s Monday!”.

By adding methods to enums, you can encapsulate behaviors related to specific enum values, making your code more readable and maintainable.

Enum with Initializers

In TypeScript, an enum member can have an initializer value assigned to it.

When an initializer is assigned, TypeScript assigns the subsequent numeric values based on the initializer value. If the initializer is not specified, TypeScript starts assigning the values from 0.

Here’s an example:

enum Direction {

Up = 1,

Down, // 2

Left, // 3

Right // 4

}

In this example, the initializer for the first member ‘Up’ is 1. The subsequent members ‘Down’, ‘Left’, and ‘Right’ do not have an explicit initializer, so TypeScript automatically assigns the values ‘2’, ‘3’, and ‘4’ respectively.

It is possible to assign an initializer to only a few members, and the rest of the members will be numbered automatically by TypeScript.

Here’s another example:

enum UserRole {

User = 1,

Moderator = 3,

Admin // 4

}

In this example, the initializer is explicitly assigned to the first two members ‘User’ and ‘Moderator’, and the subsequent member ‘Admin’ does not have an initializer. Therefore, TypeScript assigns the value ‘4’ automatically to ‘Admin’.

Enum members with initializers are useful when you want to control the numbering of enum members or specify specific values for some members in the enum.

Enum Merging

Enum merging is a feature in TypeScript that allows you to extend or modify existing enums. When two enums with the same name are declared in the same scope, TypeScript merges them into a single enum with the combined values.

Merging Enums with the Same Name

When merging enums, the resulting enum will contain all the values from both enums. The values will be sorted in the order they are declared, with duplicate values filtered out.

For example, consider the following code:

“`typescript

enum Color {

Red,

Green,

Blue

}

enum Color {

Yellow = 3,

Pink

}

console.log(Color);

“`

The output will be:

“`

{

0: “Red”,

1: “Green”,

2: “Blue”,

3: “Yellow”,

4: “Pink”,

Red: 0,

Green: 1,

Blue: 2,

Yellow: 3,

Pink: 4

}

“`

In this example, two enums with the name “Color” are declared. The second enum extends the first enum by adding two new values: “Yellow” and “Pink”. The resulting merged enum contains all the values from both enums.

Enum Merging Rules

When merging enums, TypeScript follows some rules to determine the resulting enum:

  1. If both enums have members with the same name, TypeScript will raise an error.
  2. If one enum has string-valued members and the other has numeric-valued members, TypeScript will raise an error.
  3. If one enum has either no-initialized members or computed members, the resulting enum will have those members.
  4. If one enum has a member with an initializer, the resulting enum will have that member.
  5. If both enums have constant members with the same value, only one member will be included in the resulting enum.

Using Merged Enums

After merging the enums, you can use the resulting enum just like any other enum. You can access enum members using dot notation or bracket notation.

“`typescript

enum Color {

Red,

Green,

Blue

}

enum Color {

Yellow = 3,

Pink

}

let myColor: Color = Color.Red;

console.log(myColor); // Output: 0

let myColor2: Color = Color.Yellow;

console.log(myColor2); // Output: 3

let myColor3: Color = Color.Pink;

console.log(myColor3); // Output: 4

“`

In this example, we use the merged enum “Color” to create variables with different values. We can access the enum members using dot notation to get the corresponding numeric values.

Conclusion

Enum merging in TypeScript allows you to extend or modify existing enums by declaring enums with the same name in the same scope. The resulting enum contains all the values from both enums.

Just keep in mind the rules for merging enums and you’ll be able to leverage this feature to create more expressive and flexible code.

Enum vs Object

Enums and objects are both ways to organize and represent collections of values. However, they have some key differences that make them useful in different situations.

Enums

Enums in TypeScript allow you to define a set of named constants. These constants can be used to represent a finite set of values that are related in some way. Each enum constant has a name and a value associated with it.

Enums are useful when you have a fixed set of values that you want to work with. For example, if you have a color property that can only take on the values “red”, “green”, or “blue”, you can define an enum with these three constants. This makes it easier to enforce type safety and avoid invalid values.

Here is an example of how an enum can be used:

enum Color {

Red = "red",

Green = "green",

Blue = "blue"

}

function printColor(color: Color) {

console.log(color);

}

printColor(Color.Red); // Output: "red"

Objects

Objects, on the other hand, are collections of key-value pairs. They allow you to define custom properties and values that are not limited to a fixed set. Objects are useful when you need more flexibility and want to define complex data structures.

Unlike enums, objects can have any number of properties and values. Each property can be of any data type, including other objects or functions. Objects are commonly used for representing real-world entities and their attributes.

Here is an example of how an object can be used:

const person = {

name: "John",

age: 30,

address: {

street: "123 Main St",

city: "New York",

state: "NY"

},

sayHello() {

console.log("Hello!");

}

};

console.log(person.name); // Output: "John"

console.log(person.address.city); // Output: "New York"

person.sayHello(); // Output: "Hello!"

When to use Enums or Objects

Enums are ideal for representing a closed set of values with a clear relationship. They help enforce type safety and make the code more readable. Use enums when you have a predefined set of possible values that won’t change frequently.

Objects, on the other hand, are better suited for representing real-world entities and their attributes. They allow for more flexibility and can easily handle dynamic data structures. Use objects when you need to define custom properties and values that are not limited to a fixed set.

Conclusion

Enums and objects are both useful tools for organizing and representing collections of values. Enums provide a way to define a fixed set of named constants that are related in some way. Objects, on the other hand, allow for more flexibility and can have any number of properties and values. The choice between enums and objects depends on the specific requirements of the situation.

FAQ:

What are enums in TypeScript?

Enums in TypeScript are a way to define a set of named constants. They allow us to define a set of possible values that a variable can have. This makes the code more readable and less error-prone.

How to define an enum in TypeScript?

To define an enum in TypeScript, we use the `enum` keyword followed by the name of the enum and the list of possible values enclosed in curly braces. For example: `enum Colors { Red, Green, Blue }`.

Can we assign custom values to enum members in TypeScript?

Yes, we can assign custom values to enum members in TypeScript. By default, the members of an enum are assigned numeric values starting from 0, but we can also assign custom values explicitly. For example: `enum Sizes { Small = 1, Medium = 2, Large = 3 }`.

Can we have string values in an enum in TypeScript?

Yes, we can have string values in an enum in TypeScript. By default, enum members are assigned numeric values, but we can assign string values explicitly. For example: `enum Direction { Up = “UP”, Down = “DOWN”, Left = “LEFT”, Right = “RIGHT” }`.

How to use enums in TypeScript?

To use an enum in TypeScript, we can simply refer to the enum name followed by the member name. For example: `let color: Colors = Colors.Red`.

What are the advantages of using enums in TypeScript?

Using enums in TypeScript brings several advantages. Firstly, it makes the code more readable and self-explanatory as the constant values have names instead of arbitrary numbers. Secondly, enums help in catching potential bugs as TypeScript’s type checking provides compile-time checks against mismatched values. Finally, enums can be used in switch statements, making the code more concise and easier to maintain.