TypeScript: TypeScript enum (enum)

Last updated: 2026-08-26

Enums are one of the few TypeScript type features that have runtime behavior—they are both a type and generate actual JavaScript objects.

1. Numeric Enumeration

(1) Basic Syntax

TYPESCRIPT
enum Direction {
  Up,       // 0(Auto-increment from 0)
  Down,     // 1
  Left,     // 2
  Right     // 3
}

let dir: Direction = Direction.Up;
console.log(dir);                // 0
console.log(Direction[0]);       // "Up"(Inverse Mapping)

(2) Custom Initial Values

TYPESCRIPT
enum Status {
  Active = 1,    // 1
  Inactive,      // 2(Auto-increment)
  Pending        // 3
}

enum HttpStatus {
  OK = 200,
  Moved = 301,
  BadRequest = 400,
  NotFound = 404,
  ServerError = 500
}

let code: HttpStatus = HttpStatus.OK;
console.log(code);  // 200

(3) Reverse Mapping of Numeric Enumerations

After compilation, numeric enumerations generate bidirectional mapping objects—you can retrieve a value by its name, or a name by its value:

TYPESCRIPT
enum Role {
  Admin = 0,
  Editor = 1,
  Viewer = 2
}

// Forward Mapping: name → value
console.log(Role.Admin);   // 0

// Inverse Mapping: value → name
console.log(Role[0]);      // "Admin"
console.log(Role[1]);      // "Editor"

JavaScript generated after compilation:

JAVASCRIPT
var Role;
(function (Role) {
  Role[Role["Admin"] = 0] = "Admin";
  Role[Role["Editor"] = 1] = "Editor";
  Role[Role["Viewer"] = 2] = "Viewer";
})(Role || (Role = {}));


2. String Enumeration

(1) Basic Syntax

Each member of a string enumeration must be explicitly assigned—there is no automatic increment:

TYPESCRIPT
enum EventType {
  Click = "click",
  Change = "change",
  Submit = "submit",
  Focus = "focus"
}

let event: EventType = EventType.Click;
console.log(event);  // "click"

(2) String enumeration has no inverse mapping

TYPESCRIPT
enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

console.log(Color.Red);       // "RED"  ✅ Forward Mapping
// console.log(Color["RED"]); // undefined ❌ String enumeration has no reverse mapping
💡 Reason: The values of numeric enumerations are numbers, which can be used as object keys; the values of string enumerations are strings, which conflict with object keys, so reverse mapping cannot be implemented.

▶ Example: Defining Order Statuses Using an Enumeration

TYPESCRIPT
enum OrderStatus {
  Pending = "PENDING",
  Processing = "PROCESSING",
  Shipped = "SHIPPED",
  Delivered = "DELIVERED",
  Cancelled = "CANCELLED"
}

function getStatusLabel(status: OrderStatus): string {
  switch (status) {
    case OrderStatus.Pending: return "Pending";
    case OrderStatus.Processing: return "Processing...";
    case OrderStatus.Shipped: return "Shipped";
    case OrderStatus.Delivered: return "Delivered";
    case OrderStatus.Cancelled: return "Canceled";
  }
}

let currentStatus: OrderStatus = OrderStatus.Processing;
console.log(`Current Status:${getStatusLabel(currentStatus)}`);
console.log(`Status Code:${currentStatus}`);
▶ Try it Yourself

Output:

TEXT 📖 Display only
Current Status:Processing...
Status Code:PROCESSING


3. Heterogeneous Enumerations

Enumerations can contain a mix of numeric and string values—but this is not recommended:

TYPESCRIPT
enum Mixed {
  No = 0,
  Yes = "YES"
}
⚠️ Not recommended: Heterogeneous enumerations can easily lead to confusion, and the official TypeScript documentation also recommends avoiding their use. In actual development, you should either use numeric enumerations exclusively or string enumerations exclusively.



4. const Enumerations

const enum Replaced by an inline expression during compilation—does not generate a JavaScript object, offering better performance but with limited functionality:

(1) Basic Syntax

TYPESCRIPT
const enum Color {
  Red = "RED",
  Green = "GREEN",
  Blue = "BLUE"
}

let c = Color.Red;
// After compilation:let c = "RED"(Direct Inline Replacement,No enumeration objects)

(2) Limitations of const Enumerations

TYPESCRIPT
const enum Direction {
  Up = "UP",
  Down = "DOWN"
}

// ❌ const Enumerations cannot use reverse mapping.
// console.log(Direction[0]);

// ❌ const Enumerations cannot be iterated over at runtime
// for (let d in Direction) { }

// ✅ Only simple value references are allowed.
let dir = Direction.Up;  // Compile to let dir = "UP"

(3) The preserveConstEnums option

If you want const enumerations to not be inlined but to retain the enumeration objects, enable preserveConstEnums: true:

TYPESCRIPT
// tsconfig.json
// "preserveConstEnums": true

const enum Status {
  Active = 1
}

let s = Status.Active;
// After compilation:Enumeration objects are still generated(But quotes are also inlined.)


5. Runtime and Type Safety of Enumerations

(1) Enumerations as Types

TYPESCRIPT
enum Role {
  Admin,
  Editor,
  Viewer
}

function checkAccess(role: Role): boolean {
  return role === Role.Admin || role === Role.Editor;
}

checkAccess(Role.Admin);   // ✅
checkAccess(0);            // ✅ Numeric enumerations accept numeric values(but ⚠️ not recommended)
// checkAccess(99);        // ✅ Compilation successful!Any number can be converted to——This is a numeric enumeration vulnerability.
🔥 The Pitfalls of Numeric Enumerations: Variables of numeric enumeration types can accept any number—let r: Role = 99 is a valid value. This is because numeric enumerations are designed with bit flags in mind. If you need strict value constraints, use string enumerations or literal union types.

(2) String enumeration is safer

TYPESCRIPT
enum Role {
  Admin = "ADMIN",
  Editor = "EDITOR",
  Viewer = "VIEWER"
}

let r: Role = Role.Admin;   // ✅
// r = "ADMIN";             // ❌ String enumeration does not accept regular strings.
// r = "SUPERADMIN";        // ❌ Only enumeration members are accepted


6. Enumerations vs. Literal Union Types

Property Enumeration Literal Union Type
Runtime code Yes (objects are created) No (pure types)
Reverse Mapping Digital Enumeration: Yes No
Iterate through all values Yes No
Value Constraints Numeric Enumeration (Looser) Strict
Code Hints Enum Member Autocomplete Union Value Autocomplete
Bundle size Increases code size Zero size
Interoperability with JS Enumeration values are custom objects Native strings/numbers

(1) Scenarios for Using Enumerations

▶ Example: Comparison of the Two Methods

TYPESCRIPT
// Method 1:Enumeration
enum Direction1 {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT"
}

// Method 2:Literal Union Types(Recommendations)
type Direction2 = "UP" | "DOWN" | "LEFT" | "RIGHT";

// The two are equivalent in terms of type constraints.
function move1(dir: Direction1): void { console.log(dir); }
function move2(dir: Direction2): void { console.log(dir); }

move1(Direction1.Up);  // ✅ "UP"
move2("UP");           // ✅ Use the string directly,Even simpler

// But enumerations can be iterated over
console.log(Object.values(Direction1));
// ["UP", "DOWN", "LEFT", "RIGHT"]

// Literal union types cannot be iterated over(Pure compile-time types)
▶ Try it Yourself

Output:

TEXT 📖 Display only
UP
UP
["UP", "DOWN", "LEFT", "RIGHT"]

▶ Example: Const Enums for Zero-Cost Type Safety

TYPESCRIPT
const enum LogLevel {
  Debug = 0,
  Info = 1,
  Warn = 2,
  Error = 3
}

function log(level: LogLevel, message: string): void {
  const prefix = ["DEBUG", "INFO", "WARN", "ERROR"][level];
  console.log(`[${prefix}] ${message}`);
}

log(LogLevel.Info, "Server started");   // Compiles to: log(1, "Server started")
log(LogLevel.Error, "Connection lost"); // Compiles to: log(3, "Connection lost")
▶ Try it Yourself

Output:

TEXT 📖 Display only
[INFO] Server started
[ERROR] Connection lost
💡 Key Point: const enum members are inlined at compile time—no enum object is emitted in the JS output, resulting in smaller bundle size.


❓ FAQ

Q Should you use enumerations?
A The TypeScript community is divided into two camps—one believes that enumerations are a distinctive feature of TypeScript and should be used, while the other believes that literal union types are lighter-weight and more recommended. Practical advice: If you only need type constraints (which is the case in most situations), use literal union types; if you need runtime behavior (such as iteration or reverse mapping), use enumerations.
Q Why do numeric enumerations accept any number?
A This is a design decision in TypeScript—numeric enumerations support bit flags (enum Perm { Read = 1, Write = 2, Execute = 4 }), and bit combinations Read | Write = 3 are valid but not included in the enumeration definition. Therefore, the numeric enumeration type has relaxed its constraints. If you do not want this behavior, use string enumerations or literal union types.
Q What is the difference between a const enum and a regular enum?
A A const enum is inlined at compile time—Color.Red is directly replaced with "RED", and no enum object is generated. The advantage is a smaller bundle size and faster runtime performance; the disadvantage is that it cannot be reverse-mapped, cannot be iterated over, and cannot be used in dynamic contexts. Prioritize using const enumerations (unless you need runtime features).
Q Can enumerations be combined with interfaces or type aliases?
A Yes. Enumeration values can be used as property types for interfaces—interface Config { role: Role }. Enumeration members can also be used as members of union types—type Mixed = Role.Admin | "superadmin". Enumerations are a unified concept of type and value, offering flexible usage.

📖 Summary

📝 Exercises

  1. Basic Problem (Difficulty ⭐): Given a string enum Season (Spring/Summer/Autumn/Winter), write a function that returns a description of the corresponding month range based on the season.
  2. Advanced Exercise (Difficulty ⭐⭐): Use const enum to define HTTP methods (GET/POST/PUT/DELETE), then define an Request interface that includes method and url properties. Create several request objects to verify the type constraints.
  3. Challenge (Difficulty: ⭐⭐⭐): Use literal union types instead of enumerations to implement a "permissions system": Define Permission = "read" | "write" | "execute" | "admin", then implement the hasPermission(userPerms: Permission[], required: Permission): boolean function to check whether a user has a specific permission (admin has all permissions).
Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏