TypeScript Enums

Enums stands for Enumerations. Enums are a new data type supported in TypeScript. It is used to define the set of named constants, i.e., a collection of related values. TypeScript supports both numeric and string-based enums. We can define the enums by using the enum keyword.

Why Enums?

Enums are useful in TypeScript because of the following:

  • It makes it easy to change values in the future.
  • It reduces errors which are caused by transporting or mistyping a number.
  • It exists only during compilation time, so it does not allocate memory.
  • It saves runtime and compile-time with inline code in JavaScript.
  • It allows us to create constants that we can easily relate to the program.
  • It will enable developers to develop memory-efficient custom constants in JavaScript, which does not support enums, but TypeScript helps us to access them.

There are three types of Enums in TypeScript. These are:

TypeScript Enums
  • Numeric Enums
  • String Enums
  • Heterogeneous Enums

Numeric Enums

Numeric enums are number-based enums, which store values as numbers. It means we can assign the number to an instance of the enum.

Example #1
snippet
enum Direction {
    Up = 1,
    Down,
    Left,
    Right,
}
console.log(Direction);

In the above example, we have a numeric enum named Direction. Here, we initialize Up with 1, and all of the following members are auto-incremented from that point. It means Direction.Up has the value 1, Down has 2, Left has 3, and Right has 4.

TypeScript Enums

According to our need, it also allows us to leave off the initialization of enumeration. We can declare the enum without initialization as below.

Example #2
snippet
enum Direction {
    Up,
    Down,
    Left,
    Right,
}

console.log(Direction);

Here, Up have the value 0, and all of the following members are auto-incremented from that point. It means Direction.Up has the value 0, Down has 1, Left has 2, and Right has 3. The auto-incrementing behavior is useful when there is no need to care about the member values themselves. But each value must be distinct from other values in the same enum.

TypeScript Enums

In TypeScript enums, it is not necessary to assign sequential values to enum members always. We can provide any values to the enum members, which looks like the below example.

Example #3
snippet
enum Direction {
    Up=1,
    Down=3,
    Left=6,
    Right=10,
}
console.log(Direction);
TypeScript Enums

Enum as a function argument

We can also use an enum as a function type or return type, which we can see in the below example.

Example
snippet
enum AppStatus {
    ACTIVE,
    INACTIVE,
    ONHOLD
} 
function checkStatus(status: AppStatus): void {
    console.log(status);
}
checkStatus(AppStatus.ONHOLD);

In the above example, we have declared an enum AppStatus. Next, we create a function checkStatus() that takes an input parameter status which returns an enum AppStatus. In the function, we check for the type of status. If status name matches, we get the matched enum member.

TypeScript Enums

Here, we can see that the value printed '2' in the last statement is not much useful in most of the scenarios. That's why it is preferred and recommended to use string-based enums.

String Enums

String enums are a similar concept to numeric enums, except that the enum has some subtle runtime differences. In a string enum, each enum values are constant-initialized with a string literal, or with another string enum member rather than numeric values.

String enums do not have auto-incrementing behavior. The benefits of using this enum is that string enums provides better readability. If we were debugging a program, string enums allow us to give a meaningful and readable value when our code runs, independent of the name of the enum member itself.

Consider the following example of a numeric enum, but it is represented as a string enum:

Example
snippet
enum AppStatus {
    ACTIVE = 'ACT',
    INACTIVE = 'INACT',
    ONHOLD = 'HLD',
    ONSTOP = 'STOP'
}
function checkStatus(status: AppStatus): void {
 
    console.log(status);
}
checkStatus(AppStatus.ONSTOP);
TypeScript Enums

In the above example, we have declared a string enum AppStatus with the same values as the numeric enum above. But string enum is different from numeric enum where string enum values are initialized with string literals. The difference between these enums is that the numeric enum values are auto-incremented, whereas string enum values need to be initialized individually.

Heterogeneous Enums

The heterogeneous enums are enums, which contains both string and numeric values. But it is advised that you don't do this unless there is a need to take advantage of JavaScript runtime behavior.

Example
snippet
enum AppStatus {
    ACTIVE = 'Yes',
    INACTIVE = 1,
    ONHOLD = 2,
    ONSTOP = 'STOP'
}
console.log(AppStatus.ACTIVE);
console.log(AppStatus.ONHOLD);
TypeScript Enums

Computed and constant members

We know that each enum members has a value associated with it. These values can be either constant or computed. We can consider enum member as constant if:

1. It is the first member of the enum and has no initializer value. In this case, it is assigned the value 0.

Example #1
snippet
// Name.Abhishek is constant:
enum Name { 
   Abhishek 
}
console.log(Name);

2. It has no initializer value, and the preceding enum member is a numeric constant. In this case, the value of the current enum member will be the value of the preceding enum member plus one.

Example #2
snippet
// All enum members in 'Name' and 'Profile' are constant.
enum Name { 
   Abhishek,
   Ravi,
   Ajay
}
enum Profile { 
   Engineer=1,
   Leader,
   Businessman
}

In TypeScript, we can say that an expression is a constant enum expression if it is:

  • A literal enum expression.
  • A reference to the previously defined constant enum member.
  • A parenthesized constant enum expression.
  • It is one of the +, -, ~ unary operators which is applied to constant enum expression.
  • +, -, *, /, %, <<, >>, >>>, &, |, ^ binary operators with constant enum expressions as operands.

In all other cases, the enum member is considered computed. The following enum example includes enum members with computed values.

Example #3
snippet
enum Weekend {
  Friday = 1,
  Saturday = getDate('Dominoz'),
  Sunday = Saturday * 40
}

function getDate(day : string): number {
    if (day === 'Dominoz') {
        return 3;
    }
}
console.log(Weekend.Saturday); 
console.log(Weekend.Sunday);
TypeScript Enums

Reverse mapping

TypeScript enums also support reverse mapping. It means we can access the value of an enum member, and also can access a member name from its value. We can understand the reverse mapping from the below example.

Note
Note: The string enum does not support reverse mapping.
Example
snippet
enum Weekend {
  Friday = 1,
  Saturday,
  Sunday
}
console.log(Weekend.Saturday);   
console.log(Weekend["Saturday"]);  
console.log(Weekend[3]);
TypeScript Enums

Enums at runtime

Enums are the real objects which exist at runtime. We can understand it from the below example.

Example #1
snippet
enum E {
    A, B, C
}

It can actually be passed around to functions, which we can see in the below example.

Example #2
snippet
function f(obj: { A: number }) {
    return obj.A;
}
// Works, since 'E' has a property named 'A' which is a number.
f(E);

Ambient enums

We can use ambient enums for describing the shape of already existing enum types.

Example
snippet
Declare enum Enum{
    X=1,
    Y,
    Z=2
}

There is mainly one difference between ambient and non-ambient enums. In regular enums, members that do not have an initializer is considered as constant if its preceding enum member is considered constant. But, an ambient (and non-const) enum member that does not have initializer is always considered computed enums.

Related Tutorial
Follow Us
https://www.facebook.com/Rookie-Nerd-638990322793530 https://twitter.com/RookieNerdTutor https://plus.google.com/b/117136517396468545840 #
Contents +