← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

TypeScript Enums vs Const Enums vs Union Types

TypeScript 2.0 Intermediate
debt(d5/e3/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list TypeScript compiler and ESLint as tools. The TypeScript compiler won't flag regular enum usage as wrong (it's valid syntax), but ESLint with TypeScript-specific rules (e.g., @typescript-eslint/prefer-string-literal-type or no-enum rules) can catch cases where union types or const enums would be preferable. This is specialist tooling that requires deliberate configuration, not a default lint rule.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix indicates preferring const enums or union types over regular enums. Replacing a regular enum with a union type or const enum is a mechanical substitution — update the declaration and update call sites within a single file or component. It's more than a one-liner (all usages must be updated) but doesn't span the whole codebase unless the enum is widely shared.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The applies_to covers web and CLI contexts broadly, but enums are typically defined in one place and their burden is felt mainly in that component or module. If the enum leaks into APIs (numeric enums in JSON), the pain is more widespread, but in a typical project the structural debt is localised to the module using the enum rather than architectural in nature.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field directly states that developers believe enums are always better than union types because they are explicit — yet string union types are fully type-safe, produce no JavaScript, and are the idiomatic TypeScript approach. Additionally, numeric enums allow Status[99] at runtime with no error, which contradicts the expectation that TypeScript's type system would catch invalid values. This contradicts how similar constructs work in other typed languages and how developers expect type safety to behave, landing solidly at t7.

About DEBT scoring →

Also Known As

enum TypeScript const enum string union union type enum

TL;DR

Three ways to define a set of named constants in TypeScript — regular enums emit JavaScript, const enums are inlined at compile time, and union types are the idiomatic zero-cost alternative.

Explanation

Regular enum: generates JavaScript object, supports reverse mapping (Direction[0] === 'Up'). Const enum: fully inlined at compile time — zero JavaScript generated, faster but no runtime access. String union type: type Direction = 'Up' | 'Down' — no JavaScript emitted, readable, tree-shakeable, and more compatible with JSON APIs. The TypeScript community trend: prefer string union types over enums for most cases; use const enums only when performance is critical and runtime access is not needed; avoid regular numeric enums (they allow invalid values).

Common Misconception

Enums are always better than union types because they are explicit — string union types are fully type-safe, produce no JavaScript, work perfectly with JSON, and are the idiomatic TypeScript approach.

Why It Matters

A numeric enum (enum Status { Active = 0 }) allows Status[99] at runtime with no error — a string union type Status = 'active' | 'inactive' makes invalid values a compile-time error and produces cleaner JSON.

Common Mistakes

  • Numeric enums in APIs — JSON serialises as numbers, not readable names.
  • Regular enums where const enums or union types would be better — unnecessary JavaScript overhead.
  • Mixing enum and non-enum values — direction: Direction | null requires careful handling.
  • Using enum as a namespace — use a regular object const as a namespace instead.

Code Examples

✗ Vulnerable
// Numeric enum — allows invalid values, generates JS:
enum Direction { Up, Down, Left, Right }
const d: Direction = 99; // No error! 99 is not a valid direction
JSON.stringify(Direction.Up); // '0' — not readable

// Regular enum generates runtime JS object:
// var Direction;
// Direction[Direction.Up = 0] = 'Up'; ...
✓ Fixed
// String union — zero JS, type-safe, readable JSON:
type Direction = 'Up' | 'Down' | 'Left' | 'Right';
const d: Direction = 'Invalid'; // Compile error!
JSON.stringify('Up'); // 'Up' — readable

// Const enum — inlined, no JS:
const enum Color { Red = 'red', Blue = 'blue' }
const c = Color.Red; // Compiled to: const c = 'red'

// Object const as namespace when runtime needed:
export const Direction = { Up: 'up', Down: 'down' } as const;
export type Direction = typeof Direction[keyof typeof Direction];

Added 16 Mar 2026
Edited 22 Mar 2026
Views 102
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 2 pings M 0 pings T 0 pings W 0 pings T 0 pings F 4 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 2 pings S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Perplexity 40 Amazonbot 14 ChatGPT 11 Google 8 Unknown AI 4 Ahrefs 4 Scrapy 4 SEMrush 3 Claude 2 Bing 1 PetalBot 1
crawler 88 crawler_json 3 pre-tracking 1
DEV INTEL Tools & Severity
🟢 Low ⚙ Fix effort: Low
⚡ Quick Fix
Prefer const enums or union types over regular enums — regular enums compile to JavaScript objects with runtime overhead; const enums are erased and union types need no runtime representation
📦 Applies To
typescript 2.0 web cli
🔗 Prerequisites
🔍 Detection Hints
Regular enum when const enum or string union type would avoid runtime overhead; numeric enum with string values accessed at runtime
Auto-detectable: ✓ Yes typescript eslint
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: File


✓ schema.org compliant