Enumerations (or enums) are a supported data type in TypeScript. Enums are used in most object-oriented programming languages like Java and C# and are now available in TypeScript too. They are one of the few features of TypeScript which isn’t a type-level extension of JavaScript. Enums allow you to define a set of named constants. Using them makes it easier to document intent or create a set of distinct cases. Today, we’ll explore the basics of TypeScript enums along with use cases, various enum types, and next steps for your learning.
We’ll cover:
This curated course will help you transition your JavaScript experience to TypeScript with hands-on practice and interactive exercises for all the fundamentals you need to know.
TypeScript enums allow you to define a set of named constants. Using them can make it easier to document intent or to create a set of distinct cases. Many programming languages, like C, C#, and Java, have an enum data type, but JavaScript doesn’t. However, TypeScript does. TypeScript has both numeric and string-based enums.
The syntax for enums is as follows:
enum States {Oregon,Washington,Idaho,Montana,Wyoming}// usagevar region = States.Washington;
Before we look more closely at a few different enum types, let’s discuss the benefits of enums in TypeScript.
Enums are a great way to organize your code in TypeScript. Let’s look at some pros:
While there are many benefits of using TypeScript enums, there are some times you shouldn’t use them, such as:
Now, let’s dive deeper into some enum types.
Numeric enums store string values as numbers. They can be defined using the enum keyword. Let’s say you wanted to store a set of different types of cars. The following example shows a numeric enum in TypeScript:
enum CarType {Honda,Toyota,Subaru,Hyundai}
The enum value CarType has four values: Honda, Toyota, Subaru, and Hyundai. Enum values start from zero and increment by one for each member, which would look something like this:
Honda = 0Toyota = 1Subaru = 2Hyundai = 3
If you want, you can initialize the first numeric value yourself like this:
enum CarType {Honda = 1,Toyota,Subaru,Hyundai}
In the above example, we initialized the first member Honda with the numeric value of one. The remaining numbers will be incremented by one.
Note: It’s not necessary to assign sequential values to your enum members. You can assign them any values you want.
String enums are similar to numeric enums, but their enum values are initialized with string values instead of numeric values. String enums have better readability than numeric enums, making it easier to debug your programs.
The following example uses the same info as the numeric enum example, but is represented as a string enum:
enum CarType {Honda = "HONDA",Toyota = "TOYOTA",Subaru = "SUBARU",Hyundai = "HYUNDAI"}// Access String EnumCarType.Toyota; //returns TOYOTACarType['Honda']; //returns HONDA
In the example, we defined the string enum CarType with the same values as the numeric enum, except the enum values are initialized as string literals.
Note: String enum values need to be individually initialized.
enum BooleanHeterogeneousEnum {Yes = 0,No = "NO",}
Take your TypeScript skills to the next level. This interactive course will introduce you to the world of advanced TypeScript and cover concepts such as generic types, discriminated unions, and much more. By the end, you’ll be able to confidently use advanced TypeScript in your professional projects.
You know that num values can be retrieved using their corresponding enum member values. With reverse mapping, you can access the value of a member and a member name from its value. Let’s look at an example:
enum CarType {Honda = 1,Toyota,Subaru,Hyundai}CarType.Subaru; // returns 3CarType["Subaru"]; // returns 3CarType[3]; // returns Subaru
CarType[3] returns its member name “Subaru” because of reverse mapping. Let’s look at another example:
enum CarType {Honda = 1,Toyota,Subaru,Hyundai}console.log(CarType)
You would see the following output in your browser console:
{'1': 'Honda','2': 'Toyota','3': 'Subaru','4': 'Hyundai',Honda: 1,Toyota: 2,Subaru: 3,Hyundai: 4}
Each value of the enum appears two times in the internally stored enum object.
You can use const enums to improve the performance of your numeric enums. They are defined using the const modifier:
const enum Enum {X = 1Y = X * 2,}
Unlike regular enums, const enums are completely removed during compilation. They can only use constant enum expressions and are inlined at use sites.
The value of an enum member can be a constant value or a computed value. The following example includes computed values:
enum CarType {Honda = 1,Toyota = getCarTypeCode('toyota'),Subaru = Toyota * 3,Hyundai = 10}function getCarTypeCode(carName: string): number {if (carName === 'toyota') {return 5;}}CarType.Toyota; // returns 5CarType.Subaru; // returns 15
If the enum includes both computed and constant members, then uninitiated enum members either come first or after other initialized members with numeric constants. This next example will show an error:
enum CarType {Toyota = getCarTypeCode('toyota'),Honda, // Error: Enum member must have initializerSubaru,Hyundai = Toyota * 3,}
You can declare the above enum like this:
enum CarType {Honda,Hyundai,Toyota = getCarTypeCode('toyota'),Subaru = Toyota * 3
One common surprise for new TypeScript users is that enums produce actual JavaScript objects at runtime. For example:
enum Color {Red,Green}
compiles to:
"use strict";var Color;(function (Color) {Color[Color["Red"] = 0] = "Red";Color[Color["Green"] = 1] = "Green";})(Color || (Color = {}));
This object is included in your final bundle, which can increase its size and prevent tree-shaking.
Now compare that to a const enum:
const enum Color {Red,Green}const color = Color.Red;
This compiles to:
const color = 0 /* Red */;
There’s no extra object — just a numeric constant. This is why many performance-sensitive projects prefer const enum. It’s worth noting that const enum requires full TypeScript compilation (not isolated transpilation), so check your build setup before using it widely.
Enums are simple at first glance, but a few lesser-known patterns and pitfalls are worth understanding:
No reverse mapping for string enums: Numeric enums support reverse mapping (Color[0] === "Red"), but string enums do not.
Order matters with computed members: If you mix computed and uninitialized members, the uninitialized ones must come after the computed ones.
Sparse or negative values: Enums can have negative or non-sequential values, but reverse mapping becomes unreliable.
Namespace merging: You can extend enums with static functions using namespaces:
enum Status {On,Off}namespace Status {export function isOn(s: Status) {return s === Status.On;}}console.log(Status.isOn(Status.On)); // ✅ true
Use this carefully — it’s powerful but can lead to tightly coupled code.
Enums are versatile, but they’re not always the right tool for the job. Here are some guidelines to keep in mind:
Use const enum for performance-sensitive code and when reverse mapping isn’t needed.
Use string enums when readability or API interoperability is important.
Use union types for simple value sets or when you want zero runtime overhead.
Validate data when converting external input (like API responses) into enums to avoid runtime errors.
Avoid massive enums — break them into smaller logical units or use objects if they grow too large.
Avoid mixing computed and static members unnecessarily — it makes code harder to reason about.
Here’s a quick comparison to help you decide when to use enums versus other approaches:
Feature | enum | const enum | Union Type | as const object |
Runtime object | Yes | No | No | Yes |
Reverse mapping | Yes | No | No | No |
Tree-shakable | No | Yes | Yes | Yes |
External data validation | Manual | Manual | Manual | Manual |
Type narrowing | Good | Good | Best | Good |
Best for... | Interop, existing code | High-performance builds | Type safety, frontend apps | Flexible configuration |
TypeScript provides many advantages for client-side developers. It’s easier to pick up than some other alternatives because you can jump in with a JavaScript background. TypeScript enums make it easier to document intent or to create a distinct set of cases.
Now that you know more about different TypeScript enums and their benefits, you’re ready to learn more about advanced TypeScript concepts. Some recommended topics to cover next are:
To get started learning these concepts, check out Educative’s text-based course, Advanced TypeScript Masterclass. In this course, you’ll explore the advanced features of TypeScript with in-browser coding exercises. By the end, you’ll be more confident in your advanced TypeScript skills, and you’ll be ready to apply them to your next project.
Happy learning!