TypeScript Enums

A reference guide to TypeScript numeric enums, string enums, reverse mappings, and compile-time constants.

TL;DR

  1. Define enumerated sets using the enum keyword declaration.
  2. Prefer string enum members for readable debugging outputs and API serialization.
  3. Use const enum declarations to inline values directly into emitted code.

String Enums

    string enum declaration

    Binds each member explicitly to an exact string value.

    enum Status {
      Pending = 'pending',
      Active = 'active',
      Rejected = 'rejected'
    }
    switch statement check

    Branches through members with compile-time type safety.

    function getBadgeColor(s: Status): string {
      switch (s) {
        case Status.Active: return 'green';
        case Status.Pending: return 'yellow';
        case Status.Rejected: return 'red';
      }
    }
    Object.values iteration

    Lists all assigned runtime values of a string enum.

    const statuses: string[] = Object.values(Status);
    console.log(statuses); // ['pending', 'active', ...]

Numeric Enums

    auto-incrementing members

    Initializes members sequentially starting from zero.

    enum Direction {
      North, // 0
      East,  // 1
      South, // 2
      West   // 3
    }
    custom initial value

    Starts numbering from an explicit numeric base.

    enum HttpCode {
      Ok = 200,
      Created = 201,
      Accepted = 202
    }
    bitwise flag enum

    Combines binary permission masks using bitwise shifts.

    enum Permission {
      Read = 1 << 0,  // 1
      Write = 1 << 1, // 2
      Exec = 1 << 2   // 4
    }
    const flags = Permission.Read | Permission.Write;

Reverse Mapping

    lookup by value

    Retrieves the string member name using its numeric index.

    enum Level { Low = 1, High = 2 }
    const label: string = Level[2]; // 'High'
    iteration pitfall

    Exposes dual keys when inspecting numeric enums directly.

    enum Mode { Dev, Prod }
    // Object.keys(Mode) yields: ['0', '1', 'Dev', 'Prod']
    filtering reverse keys

    Removes numeric indices when enumerating member names.

    const names = Object.keys(Mode).filter(
      key => isNaN(Number(key))
    );
    console.log(names); // ['Dev', 'Prod']

Const Enums

    const enum declaration

    Inlines member literals directly into calling sites.

    const enum Priority {
      Low = 10,
      High = 50
    }
    const taskPriority = Priority.High; // emits 50
    zero runtime footprint

    Emits no JavaScript lookup objects during compilation.

    // TypeScript generates no runtime object for Priority
    preserveConstEnums option

    Emits runtime objects alongside inlining for debugging.

    // Set in tsconfig.json
    {
      "compilerOptions": {
        "preserveConstEnums": true
      }
    }

Object as Const Alternative

    as const object pattern

    Uses standard JavaScript objects with literal assertions.

    const LogLevel = {
      Info: 'info',
      Warn: 'warn',
      Error: 'error'
    } as const;
    derived union type

    Extracts union types directly from object properties.

    type Keys = keyof typeof LogLevel;
    type LogLevel = (typeof LogLevel)[Keys];
    // 'info' | 'warn' | 'error'
    idiomatic alternative

    Avoids TypeScript-specific runtime syntax extensions.

    function log(level: LogLevel, msg: string) {
      console.log(`[${level.toUpperCase()}]: ${msg}`);
    }

Tips

  1. Explicitly initialize the first numeric enum member with a positive number to avoid treating zero as falsy.
  2. Extract all string values from an enum at runtime using the standard Object.values() helper function.

Warnings

  1. Numeric enums generate reverse mapping keys that appear unexpectedly during iterations over Object.keys() in runtime JavaScript code.
  2. Avoid using const enum declarations when building shared packages consumed by tools with isolatedModules enabled.

In Practice

FAQ