A Typescript enum allows us to define the collection of related values to be used by name. They make the code easier to read. You may use them when you want to limit the values that a variable can take to a small set of possible values. Javascript does not support enums, hence typescript creates runtime artifact to support them ( Except, const enum
which do not have a runtime artifact). TypeScript provides both numeric and string-based enums.
Table of Contents
Where to use Enum
There are many use cases, where the enum is very useful. For Example, directions can only take four values north
, east
, south
, and west
. We can use codes like N
, E
, S
, & W
to represent them. Another example is days of the week, which you can represent as 1 to 7. Traffic lights are another example where variable takes finite values like green
, yellow
, & red
The enums make the core more readable and less error-prone. For Example, using codes like 1
,2
, etc to represent days of the week is less readable compared to the Weekdays.Sunday
, Weekdays.Monday
.
It also makes it easier to change the values in the future, without breaking the code. For Example, if you decide to use the number instead of N
, E
, S
, & W
for directions, you can do so easily.
You can also make use of the string literal types or numeric literal types along with the union types. These literal types do not have runtime artifacts and hence may be preferable over the Enum
. Choose one based on your preference..
How to Create Enum
We define an enum
by using the enum
keyword, followed by the name of the enum (Weekdays
). Then we define the members of the enum. Each member must have a name (monday
, tuesday
, etc) and value (1
,2
, etc). The members are separated by a comma. The trailing comma is allowed & ignored. If we omit the value of a member, then the TypeScript increments the value of the preceding member by one and assigns it to the current member: If the preceding member is a string and error is thrown.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | enum Weekdays { Monday = 1, Tuesday = 2, Wednesday = 3, Thursday = 4, Friday = 5, Saturday = 6, Sunday = 7 } console.log(Weekdays.Monday) //1 console.log(Weekdays["Monday"]) //1 console.log(Weekdays["1"]) //Monday let holiday=Weekdays.Sunday; console.log(holiday); //7 console.log(typeof Weekdays) //object console.log(typeof holiday) //number |
In the above example, we have initialized the values. But If we omit the values, then the typescript initializes it with the values starting from 0
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | enum Weekdays { Monday, //Initialized with zero Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } console.log(Weekdays.Monday) //0 console.log(Weekdays["Monday"]) //0 console.log(Weekdays["1"]) //Tuesday |
You will get the nice intellisense help, when you use them.

we can use the quote in the names of enum members as shown below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | enum Weekdays { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" } console.log(Weekdays.Monday) //0 console.log(Weekdays["Monday"]) //0 console.log(Weekdays["1"]) //Tuesday |
Types of Enum
There are three types enum
‘s in Typescript.
- Numeric enums
- String enums
- Heterogeneous enums (both string & numbers)
Typescript enum does not support any other types other than numbers and strings as its member.
Numeric Enums
The Numeric enum
stores the values as a number. You can define an enum
without assigning a value as shown below. The Typescript automatically assigns the numeric values starting from 0
. You can see from the following example that the Car,plane & train
gets the value 0,1 & 2
respectively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | enum VehcileType { Car, //0 Plane, //1 Train //2 } console.log(VehcileType.Plane) //1 console.log(VehcileType["Plane"]) //1 console.log(VehcileType[1]) //Plane //Get the name from the Enum Member. console.log(VehcileType[VehcileType.Plane]) //Plane |
You can provide a starting number as shown in the example below. The plane
& train
automatically gets ( 3
& 4
). i.e. the next available number.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | enum VehcileType { Car=2, Plane, Train } console.log(VehcileType) //Output { '2': 'Car', '3': 'Plane', '4': 'Train', Car: 2, Plane: 3, Train: 4 } |
The following example shows how to use enum as a return type
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | enum VehcileType { Car=1, Plane, Train } function getVehicle(name: string): VehcileType | undefined { if ( name === 'ferrari') { return VehcileType.Car; } else { return undefined } } console.log(getVehicle('ferrari')); //output 1 |
Computed enum
We can also include the members with computed values. They are allowed only in the case of numeric enums. The string & heterogeneous enums do not support computed enums.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | enum VehcileType { Car=1, Plane, Train= 5 + VehcileType.Plane } console.log(VehcileType) //OUTPUT { '1': 'Car', '2': 'Plane', '7': 'Train', Car: 1, Plane: 2, Train: 7 } |
You can use any function. The following code generates a random number from 10 to 20. Hence you will get a different number for the train on each run.
1 2 3 4 5 6 7 8 9 10 11 12 13 | enum VehcileType { Car=1, Plane, Train= getRandomNumberBetween(10,20) } console.log(VehcileType) function getRandomNumberBetween(min,max){ return Math.floor(Math.random()*(max-min+1)+min); } |
String Enums
We can also use the strings instead of numbers as values.The only difference is that the we must initialize the values.
1 2 3 4 5 6 7 8 9 10 | enum VehcileType { Car="Car", Plane="Plane", Train="Train" } console.log(VehcileType.Car); //Car console.log(VehcileType["Car"]); //Car |
Use it in a function as shown below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | enum VehcileType { Car="C", Plane="P", Train="T" } let vehicle = VehcileType.Plane printName(vehicle); function printName(val: VehcileType) { switch (val) { case VehcileType.Car: console.log("It is a Car"); break; case VehcileType.Plane: console.log("It is a Plane."); break; case VehcileType.Train: console.log("It is a Train."); break; default: console.log("No such vehicle"); break; } } |
1 2 3 4 5 6 7 8 | const value:VehcileType =VehcileType.Car ; if (value === VehcileType.Car || value === VehcileType.Train){ console.log('Please choose a plane'); console.log(value); } |
Heterogeneous Enums
The Heterogeneous enums allows mix of both string & number.
If you do not provide an initial value, the typescript will automatically assign a number incremented by one from the previous value. If the previous value is a string
, then it will result in an error.
For Example, Train
gets the value 2 here
1 2 3 4 5 6 7 8 9 10 11 12 | enum VehcileType { Car="C", Plane=1, Train } console.log(VehcileType) //OUTPUT { '1': 'Plane', '2': 'Train', Car: 'C', Plane: 1, Train: 2 } |
This results in an error Enum member must have initializer
.
1 2 3 4 5 6 7 | enum VehcileType { Car="C", Plane, //Error Enum member must have initializer. Train } |
Reverse Mapping of Enum
The Typescript generates a reverse mapping for numeric enum members. For Example
1 2 3 4 5 6 7 | enum VehcileType { Car, Plane, Train } |
The Compiler emits the following code. As you can see from the code, the compile generates both the forward mapping (VehcileType["Car"] = 0
) and reverse mapping (VehcileType[0] = "Car";
) is a single statement VehcileType[VehcileType["Car"] = 0] = "Car";
1 2 3 4 5 6 7 8 | var VehcileType; (function (VehcileType) { VehcileType[VehcileType["Car"] = 0] = "Car"; VehcileType[VehcileType["Plane"] = 1] = "Plane"; VehcileType[VehcileType["Train"] = 2] = "Train"; })(VehcileType || (VehcileType = {})); |
Which means you can get the value of an enum from its name VehcileType["Car"]
or get the name of enum from its value (VehcileType[0]
)
1 2 3 4 5 | console.log(VehcileType.Car) //0 console.log(VehcileType["Car"]) //0 console.log(VehcileType[0]) //Car |
The reverse mapping for numeric enum members works even in Heterogeneous Enums with number values as shown below. The string enum members do not support reverse mappings
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | enum VehcileType { Car="C", Plane="P", Train=10 } console.log(VehcileType.Plane) //P console.log(VehcileType["Plane"]) //P console.log(VehcileType["P"]) //undefined //ERROR console.log(VehcileType.Train) //10 console.log(VehcileType["Train"]) //10 console.log(VehcileType[10]) //Train //Works |
Transpiled code.
1 2 3 4 5 6 7 8 | var VehcileType; (function (VehcileType) { VehcileType["Car"] = "C"; //No Reverse Mapping for strings VehcileType["Plane"] = "P"; // VehcileType[VehcileType["Train"] = 10] = "Train"; //Reverse Mapping })(VehcileType || (VehcileType = {})); |
Const Enums
If an enum is prefixed with the keyword const
, it doesn’t get transpiled. i.e. no javascript code is emitted. Instead, the compiler will replace the value of its member directly in the transpiled code, wherever they are used.
Since they do no have runtime representation, you cannot use computed memeber
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | const enum VehcileType { Car, Plane, Train } console.log(VehcileType.Car) //0 console.log(VehcileType.Plane) //1 console.log(VehcileType["Car"]) //0 console.log(VehcileType["Plane"]) //1 console.log(VehcileType[0]) //ERROR console.log(VehcileType[1]) //ERROR //Transpiled Code // console.log(0 /* Car */); //0 //VehcileType.Car is replaced with its value 0 console.log(1 /* Plane */); //1 console.log(0 /* "Car" */); //0 console.log(1 /* "Plane" */); //1 console.log(VehcileType[0]); //ERROR console.log(VehcileType[1]); //ERROR |
Type Checking
The Typescript performs a loose type checking when number members are involved. For example the someFn
accepts VehcileType
as argument. But someFn
also accepts any number. Invoking someFn(100)
with 100 as argument does not throw any errors.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | enum VehcileType { Car, Plane, Train } function someFn(val:VehcileType) { console.log(val); } someFn(VehcileType.Car) //OK someFn(100) //NO ERROR someFn("Test") //Error someFn("C") //Error someFn("Car") //Error |
But in case of string
enums
it works as expected.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | enum VehcileType { Car="C", Plane="P", Train="T" } function someFn(val:VehcileType) { console.log(val); } someFn(VehcileType.Car) //OK someFn(100) //Error someFn("Test") //Error someFn("C") //Error someFn("Car") //Error |
The loose checking of type exists when you mix numbers & strings as in Heterogeneous enums.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | enum VehcileType { Car="C", Plane="P", Train=10 } function someFn(val:VehcileType) { console.log(val); } someFn(VehcileType.Car) //OK someFn(100) //NO ERROR someFn("Test") //Error someFn("C") //Error someFn("Car") //Error |
does VehcileType was supposed to be VehicleType?
Exactly, it is a typo