Enums
TypeScript Programming
Enums in TypeScript
Enums (short for enumerations) are a feature that TypeScript adds on top of JavaScript, allowing you to define a set of named constants. They make your code more readable and maintainable by replacing magic numbers and string literals with descriptive names. When you see Status.Active in code, its meaning is immediately clear, whereas the number 1 or the string "active" requires context to understand. Enums are one of the few TypeScript features that generate runtime code rather than being erased during compilation.
Numeric Enums
By default, enums in TypeScript are numeric. The first member starts at 0, and subsequent members auto-increment by 1. You can also set custom starting values or assign specific values to individual members.
// Default numeric enum — starts at 0
enum Direction {
Up, // 0
Down, // 1
Left, // 2
Right, // 3
}
let move: Direction = Direction.Up;
console.log(move); // 0
console.log(Direction[0]); // "Up" (reverse mapping)
// Custom starting value
enum StatusCode {
OK = 200,
Created = 201,
BadRequest = 400,
NotFound = 404,
ServerError = 500,
}
function handleResponse(code: StatusCode): void {
if (code === StatusCode.OK) {
console.log("Request succeeded");
} else if (code === StatusCode.NotFound) {
console.log("Resource not found");
}
}
handleResponse(StatusCode.OK);
String Enums
String enums require each member to be initialized with a string literal. They do not auto-increment, but they produce more readable output in logs and debugging since the runtime value is a meaningful string rather than a number. String enums do not support reverse mapping.
enum Color {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
Yellow = "YELLOW",
}
function paintWall(color: Color): void {
console.log(`Painting wall: ${color}`);
}
paintWall(Color.Red); // "Painting wall: RED"
// paintWall("RED"); // Error: Argument of type '"RED"' is not
// // assignable to parameter of type 'Color'
// Use in switch statements
function getHex(color: Color): string {
switch (color) {
case Color.Red: return "#FF0000";
case Color.Green: return "#00FF00";
case Color.Blue: return "#0000FF";
case Color.Yellow: return "#FFFF00";
}
}
Heterogeneous Enums
TypeScript allows mixing string and numeric members in a single enum, though this is rarely useful and generally discouraged for clarity.
enum Mixed {
No = 0,
Yes = "YES",
}
Const Enums
Const enums are a performance optimization. They are completely erased during compilation, and their values are inlined at every usage site. This eliminates the generated enum object and reduces bundle size. The trade-off is that you lose reverse mapping and cannot use computed members.
const enum Priority {
Low = 1,
Medium = 2,
High = 3,
Critical = 4,
}
let taskPriority = Priority.High;
// Compiled JS: let taskPriority = 3; (inlined, no enum object)
function isUrgent(priority: Priority): boolean {
return priority >= Priority.Critical;
}
Enums as Union Types
Each enum member becomes its own type, and the enum itself becomes a union of all its members. This enables powerful narrowing in switch statements and ensures exhaustive checking.
enum Shape {
Circle = "circle",
Square = "square",
Triangle = "triangle",
}
function getArea(shape: Shape, size: number): number {
switch (shape) {
case Shape.Circle:
return Math.PI * size * size;
case Shape.Square:
return size * size;
case Shape.Triangle:
return (Math.sqrt(3) / 4) * size * size;
// If you add a new Shape member and forget to handle it here,
// TypeScript will warn you (with --strictNullChecks)
}
}
Tip: Many modern TypeScript codebases prefer union types of string literals (type Direction = "up" | "down" | "left" | "right") over enums because they are simpler, produce no runtime code, and work well with type narrowing. Use enums when you need reverse mapping or when working with numeric constants.
Key Takeaways
- Numeric enums auto-increment from 0 and support reverse mapping from value to name.
- String enums require explicit initialization and produce readable runtime values.
- Const enums are inlined at compile time for better performance but lose reverse mapping.
- Enums work well in switch statements with exhaustive checking.
- Consider string literal union types as a lighter alternative to enums in many cases.