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).