All We Need to Know About TypeScript Enums
Tags: typescript, javascript, oop, beginners
Published: 2020-01-05 22:29:49

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

If we want to define constants in JavaScript, we can use the `const` keyword. With TypeScript, we have another way to define a set of constants call the enums. Enums let us define a list of named constants. It’s handy for defining an entity that can take on a few possible values. TypeScript provides both numeric and string-based enums.

Numeric Enums
=============

TypeScript has an enum type that’s not available in JavaScript. An enum type is a data type that has a set named values called elements, members, enumeral or enumerator of the type. They’re identifiers that act like constants in the language. In TypeScript, a numeric enum has a corresponding index associated with it. The members start with the index 0 by default, but it can be changed to start at any index we like and the subsequent members will have indexes that increment from that starting number instead. For example, we can write the following code to define a simple enum in TypeScript:

```typescript
enum Fruit { Orange, Apple, Grape };
```

We can use enums by accessing the members like any other property. For example, in the `Fruit` enum, we can accept the members like in the following code:

```typescript
console.log(Fruit.Orange);  
console.log(Fruit.Apple);  
console.log(Fruit.Grape);
```

Then `console.log` from the code above should get us 0 since we didn’t specify a starting index for the enum. We can specify the starting index of an enum with something like in the following code:

```typescript
enum Fruit { Orange = 1, Apple, Grape };  
console.log(Fruit.Orange);  
console.log(Fruit.Apple);  
console.log(Fruit.Grape);
```

Then we get the following logged from each `console.log` statement in order:

```bash
1  
2  
3
```

We can specify the same index for each member, but it wouldn’t be very useful:

```typescript
enum Fruit { Orange = 1, Apple = 1, Grape };  
console.log(Fruit.Orange);  
console.log(Fruit.Apple);  
console.log(Fruit.Grape);
```

Then we get:

```bash
1  
1  
2
```

from the `console.log`. As we can see, we specify the index pretty much however we want to change it. We can even have negative indexes:

```typescript
enum Fruit { Orange = -1, Apple, Grape };  
console.log(Fruit.Orange);  
console.log(Fruit.Apple);  
console.log(Fruit.Grape);
```

Then we get:

```typescript
-1  
0  
1
```

from the `console.log`. To get an enum member by its index, we can just use the bracket notation like we access array entries by its index. For example, we can write the following code:

```typescript
enum Fruit { Orange, Apple, Grape };  
console.log(Fruit[0]);  
console.log(Fruit[1]);  
console.log(Fruit[2]);
```

Then we get:

```bash
Orange  
Apple  
Grape
```

Numeric enums can have computed values assigned to their members. For example, we can write a function to get a value for each enum member like in the following code:

```typescript
const getValue = () => 2;
enum Fruit {  
  Orange = getValue(),  
  Apple = getValue(),  
  Grape = getValue()  
};
```

Note that we assigned a return value for each member. If we don’t do that for all of them like in the following code:

```typescript
const getValue = () => 2;
enum Fruit {  
  Orange = getValue(),  
  Apple = getValue(),  
  Grape  
};
```

Then the TypeScript compiler won’t compile the code and will give an error “Enum member must have initializer.(1061)“. We can mix both constant and computed values in one enum, so we can write something like:

```typescript
const getValue = () => 2;
enum Fruit {  
  Orange = getValue(),  
  Apple = 3,  
  Grape = getValue()  
};
```

String Enums
============

TypeScript enum members can also have string values. We can set the values of each member to a string by assigning strings to them like in the following code:

```typescript
enum Fruit {  
  Orange = 'Orange',  
  Apple = 'Apple',  
  Grape = 'Grape'  
};
```

However, unlike numeric enums, we can’t assign computed values to them. For example, if we have the following:

```typescript
const getValue = () => 'Orange';
enum Fruit {  
  Orange = getValue(),  
  Apple = 'Apple',  
  Grape = 'Grape'  
};
```

Then we would get the TypeScript compiler error message “Computed values are not permitted in an enum with string-valued members. (2553)” since computed values aren’t allowed for string-valued enums. String enums don’t have auto-incrementing behavior like numeric enums since they don’t have numerical values, but the values of the enum members are much clearer since each value is a meaningful value that’s clear to any human reading it.

In a single enum, we can have some members having numeric values and others having string values like in the following code:

```typescript
enum Fruit {  
  Orange = 2,  
  Apple = 'Apple',  
  Grape = 'Grape'  
};
```

However, this is more confusing than having a single type of value for all enum members, so it’s not recommended to have mixed value types for different members for an enum.

Computed and Constant Members
=============================

Each enum member has a value associated with it which can either be constant or computed. An enum member is constant if the first member in the enum has no value explicitly assigned to it, which means that it’s assigned the value 0 by default. It can also be considered constant if it doesn’t have an explicit value assigned to it and the preceding enum member was a numeric constant, which means that it’ll have the value of the preceding member plus one. For example, if we have:

```typescript
enum Fruit { Orange = 1, Apple, Grape };
```

Then `Apple` and `Grape` are both constant members since it’ll be automatically assigned the values 2 and 3 respectively. They’re also considered constant if each member has string values assigned to them. Also, if an enum references a previously defined enum member which can be from the same or a different enum. The return value of any operation assigned to constant enums like surrounding an enum expression with parentheses, doing unary arithmetic or bitwise operations to an enum expression like `+`, `-`, `~`, or doing binary arithmetic or bitwise operations like, `-`, `*`, `/`, `%`, `<<`, `>>`, `>>>`, `&`, `|`, `^` with enum expressions as operands are all considered constant enum expressions.

For example, the following enum is an enum with constant enum expressions:

```typescript
enum Fruit {  
  Orange = 1 + 2,  
  Apple =  1 + 3,  
  Grape = 1 + 4  
};
```

The expressions are constant since they’re computed from any variable or return values of functions. Each member has values that's computed from number values, rather than numbers assigned to variables or returned from functions.

The following is also an example of an enum with constant members:

```typescript
enum Fruit {  
  Orange = 1 + 2,  
  Apple =  1 + 3,  
  Grape = Orange + Apple  
};
```

All the members including the last one are constant since the value of `Grape` is computed from `Orange` and `Apple` which are constant. Bitwise operations with both operands being constant values are also considered constants as we have in the following code:

```typescript
enum Fruit {  
  Orange = 1 | 2,  
  Apple =  1 + 3,  
  Grape = 'abc'.length  
};
```

Anything else not described above is considered computed values. For example, if we have:

```typescript
enum Fruit {  
  Orange = 1 + 2,  
  Apple =  1 + 3,  
  Grape = 'abc'.length  
};
```

Then `Grape` is a computed member since the expression we assigned to `Grape` is not computed from any constant member, and it involves getting a property from an object, which isn’t computed from a constant value.

If we want to define constants in JavaScript, we can use the `const` keyword. With TypeScript, we have another way to define a set of constants call the enums. Enums let us define a list of named constants. It’s handy for defining an entity that can take on a few possible values. TypeScript provides both numeric and string-based enums. TypeScript allows enum members to have numeric and string values. They can also be computed from values for other enum members or from any other expression we wish to assign. Constant enums are the ones that are computed from actual numerical values as operands or with actual values assigned to the member. All other values are computed member values.