Core Concepts7 min read · Updated 2025-06-01

TypeScript Enums Explained: Numeric, String & Const Enums

A complete guide to TypeScript enums — numeric enums, string enums, const enums, and why many TypeScript experts recommend union types instead.

💡 Practice these concepts interactively with AI feedback

Start Practicing →

TypeScript Enums Explained

Numeric Enums

enum Direction {
  Up,     // 0
  Down,   // 1
  Left,   // 2
  Right,  // 3
}

console.log(Direction.Up) // 0 console.log(Direction[0]) // 'Up' — reverse mapping exists!

enum Status { Draft = 1, // manual start value Published, // 2 Archived, // 3 }

Numeric enums generate both forward (Name → value) and reverse (value → Name) mappings in the compiled output.

String Enums

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

console.log(Color.Red) // 'RED' console.log(Color['RED']) // ❌ No reverse mapping — string enums don't have it

String enums are more debuggable (readable values in logs) and don't have the reverse mapping issue of numeric enums. They are more widely recommended.

Const Enums

const enum Weekday {
  Mon = 1, Tue, Wed, Thu, Fri, Sat, Sun
}

const today = Weekday.Mon // Compiles to: const today = 1 — enum is fully inlined, no object emitted

Const enums are erased entirely at compile time — values are inlined wherever they're used. This reduces bundle size but means the enum doesn't exist at runtime. Avoid them in library code where consumers may use the enum by name.

Heterogeneous Enums (Avoid)

// ❌ Don't do this — mixing types is confusing
enum Mixed {
  No = 0,
  Yes = 'YES',
}

The Case Against Enums

Many TypeScript experts recommend using union types instead:

// ❌ Enum approach
enum Direction { Up = 'UP', Down = 'DOWN', Left = 'LEFT', Right = 'RIGHT' }
function move(dir: Direction) { / / }
move(Direction.Up)

// ✅ Union type — simpler, no runtime artifact, more flexible type Direction = 'UP' | 'DOWN' | 'LEFT' | 'RIGHT' function move(dir: Direction) { / / } move('UP') // direct string — no enum import needed

// ✅ Object with as const — best of both worlds const Direction = { Up: 'UP', Down: 'DOWN', Left: 'LEFT', Right: 'RIGHT', } as const

type Direction = typeof Direction[keyof typeof Direction] // 'UP' | 'DOWN' | 'LEFT' | 'RIGHT' move(Direction.Up) // 'UP' — dot notation like enum move('UP') // also valid — string literals work too

When to Use Each

| Approach | Use When | |---|---| | Numeric enum | Interop with C# or legacy code, database flags | | String enum | Debuggable runtime values needed, team is familiar with enums | | Const enum | Bundle size critical, no library consumers, no reverse mapping needed | | Union type | New TypeScript code, no runtime artifact needed, simple cases | | const object + typeof | Need dot notation AND string literals to work, maximum flexibility |

The TypeScript team itself uses const objects with as const extensively in their own codebase.

Practice TypeScript questions at [JSPrep Pro](/auth).

Put This Into Practice

Reading articles is passive. JSPrep Pro makes you actively recall, predict output, and get AI feedback.

Start Free →Browse All Questions

Related Articles

Deep Dive
We Built a RAG-Powered AI Question Engine Into a JavaScript Interview Platform — Here's Exactly How It Works
12 min read
Build Systems
Monorepo with Turborepo vs Nx: The Complete Comparison (2025)
9 min read
Core Concepts
map() vs forEach() in JavaScript: Which One to Use and Why It Matters
7 min read