typescript enums
Nov 19 2018 06:49pm | | Share

Enums in TypeScript

By Ronak Nagda

Introduction

Enumerated type a.k.a. enumeration or enum is a data type allowing us to define a set of related member values. Using enums can make it easier to document and create a set of distinct cases which are all part of the same parent group. Various programming languages like C, C++, and Java provide an enum data type, but JavaScript does not support it. Fortunately, TypeScript now provides both numeric and string-based enums.

 

Example and Transpilation

Example of a TypeScript enum:

 

enum Color {

    Red,

    Green,

    Blue

}

 

var paint = Color.Red;

 

The variable for ‘paint’ now could only be assigned to one of the three enum members defined. Trying to assign any other member would throw a runtime error.

 

For the above enum, the JavaScript (ES5) transpiler emits a lookup table which appears as follows in the corresponding js file:

 

var Color;

(function (Color) {
  Color[Color["Red"] = 0] = " Red";
  Color[Color["Green"] = 1] = " Green";

  Color[Color["Blue"] = 2] = " Blue";
})( Color || (Color = {}));

 

Now if you write Color.Red in TypeScript it emits Color.Red in JavaScript and evaluates to 0. Whereas Color[0] actually evaluates to “Red”. The reverse lookup options are available in enums and are easy to use.

 

Numeric Enums

Numeric enums are the most common usage of enums, especially if you are coming from other languages. In the example mentioned above, Red has the value of 0, Green is 1 and so on. This auto-incrementing behavior is really useful when all you really care about is the unique values being assigned to each member rather than the actual value itself.  

 

However, you have an option to change the number associated with any enum member by assigning it as seen below:

 

enum Color {

    Red = 2,

    Green,

    Blue

}


 

Here, the Red is assigned value of 2, and hence Green is auto-incremented to 3 and so on.

 

String Enums

TypeScript 2.4 implemented one of the most requested features: string enums, or, to be more precise, enums with string-valued members.

It is now possible to assign a string value to an enum member:

 

enum Color {

    Red = “Red”,

    Green = “Green”,

    Blue = “Blue”

}

 

String enums do not have auto-incremental values like number enums, nor do they have any numbers associated to their members. So, Color.Red and Color[‘Red’] both compute to “Red”.

String enums are easier to read and debug providing a more meaningful value. String enums could be used to do simple string comparisons and computations.

 

Heterogeneous Enums

Enums could also be mixed with string and number member values, but it is not advisable unless you have a really good reason to use this and enhance the performance of JavaScript’s runtime behavior. Here’s an example:

 

enum HeterogeneousBoolean {

    False = 0,

    True = “True”

}

 

Const Enums

A const enum is same as a regular enum, except that no object is generated by JavaScript transpiler at compile time. Instead, the literal values are substituted where the const enum is used. This means you cannot index by an arbitrary value. Here’s an example:

 


const enum Color { Red, Green }

 

The values for Color.Red and Color[“Red”] evaluate to value ‘0’ but no code is actually emitted for const enums hence, no reverse mapping is possible. Color[0] will encounter an error at runtime, since there is no lookup table available.

Const enums are useful for performance reasons with reduced memory consumption but they come at the cost of readability and reverse mapping.

 

Computed Enums

Numeric enums could include members with computed values.

 

enum Color {

    Red = 1,

    Green = Red * 5,

    Blue = Green + Red

}

 

Color.Green      // returns 5

Color.Blue       // returns 6


 

Here the enum values for Green and Blue rely on the previously declared member value of Red. So, if the value of Red were to change, all the other member values will get affected.

 

Reverse Mapping

Numeric enums in TypeScript also provide an option for reverse mapping. That means you can access enum members from its enum values.

 

enum Color {

    Red,

    Green,

    Blue

}

 

Color.Blue       // returns 2

Color[“Blue”]    // returns 2

Color[2]         // returns Blue

 

 

Here Color[2] returns its member name “Blue” because of the reverse mapping using the JavaScript transpiler’s lookup table mentioned above.

 

Conclusion

So, with all enums available at your fingertips, how do you decide which enum to use? If in doubt, better to stick with number enums and string enums. String enums provide better readability and are easier to debug since we are dealing with meaningful string literals instead of arbitrary numeric values. If you are really trying to achieve performance improvements, you may choose a const enum or an alternative method.

 

There are further types of enums available like declare, declare const, union, ambient and so on. The usages of such enums is limited. Please refer to the websites mentioned below to learn all about these enum types.

 

References:

Official TypeScript Website (https://www.typescriptlang.org/docs/handbook/enums.html)

Medium (https://medium.com/@katbusch/typescript-enums-explained-e5f9a101afc9)