SyntaxStudy
Sign Up
TypeScript Const Enums and Enum Patterns
TypeScript Beginner 1 min read

Const Enums and Enum Patterns

Const enums are declared with the const keyword before enum. Unlike regular enums, const enums are completely erased during compilation — all usages are inlined as their literal values. This results in zero runtime overhead and smaller bundle sizes. The trade-off is that const enum values cannot be computed at runtime, and they may cause issues when used across separate compilation units. When you need enum-like behaviour without the runtime overhead of a full enum, you can use a const object with as const. This pattern is sometimes called a "POJO enum" and is increasingly preferred because it works seamlessly with ESM, avoids the const enum cross-module pitfalls, and still provides type safety through typeof and the keyof operator. Enums participate in TypeScript's type system in important ways. You can use an enum type as a function parameter, meaning only valid enum members are accepted. You can also extract the type of enum values using the typeof operator combined with a keyof lookup. These patterns allow you to build type-safe APIs around enum values.
Example
// Const enum — values are inlined, no runtime object
const enum Weekday {
    Monday = 1,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
}

const day: Weekday = Weekday.Wednesday; // compiled to: const day = 3;

// POJO enum pattern — avoids const enum pitfalls
const Color = {
    Red:   "RED",
    Green: "GREEN",
    Blue:  "BLUE",
} as const;

type Color = typeof Color[keyof typeof Color]; // "RED" | "GREEN" | "BLUE"

function paintWall(color: Color): void {
    console.log(`Painting with ${color}`);
}

paintWall(Color.Red);  // OK
// paintWall("PURPLE"); // Error

// Iterating over an enum
enum Permission {
    Read  = "READ",
    Write = "WRITE",
    Admin = "ADMIN",
}

const allPermissions = Object.values(Permission);
// ["READ", "WRITE", "ADMIN"]

// Enum bitflags (numeric)
const enum FileMode {
    None    = 0,
    Read    = 1 << 0, // 1
    Write   = 1 << 1, // 2
    Execute = 1 << 2, // 4
}

const mode = FileMode.Read | FileMode.Write; // 3
const canRead  = (mode & FileMode.Read)  !== 0; // true
const canExec  = (mode & FileMode.Execute) !== 0; // false