gotchatypescriptModerate
TypeScript enums have surprising runtime behavior
Viewed 0 times
enum runtimeconst enumunion typestring literalas const
Problem
TypeScript numeric enums generate runtime JavaScript objects with reverse mappings. This increases bundle size and allows invalid values. enum Status { Active = 0, Inactive = 1 } allows Status[99] with no error.
Solution
Prefer const enums or union types:
// Union type (no runtime overhead)
type Status = 'active' | 'inactive';
// Const enum (inlined at compile time, no runtime object)
const enum Direction { Up, Down, Left, Right }
// Compiles to: const d = 0; (no Direction object)
// If you need runtime iteration, use 'as const' object
const STATUS = { Active: 'active', Inactive: 'inactive' } as const;
type Status = typeof STATUS[keyof typeof STATUS]; // 'active' | 'inactive'
Object.values(STATUS); // ['active', 'inactive']
// Union type (no runtime overhead)
type Status = 'active' | 'inactive';
// Const enum (inlined at compile time, no runtime object)
const enum Direction { Up, Down, Left, Right }
// Compiles to: const d = 0; (no Direction object)
// If you need runtime iteration, use 'as const' object
const STATUS = { Active: 'active', Inactive: 'inactive' } as const;
type Status = typeof STATUS[keyof typeof STATUS]; // 'active' | 'inactive'
Object.values(STATUS); // ['active', 'inactive']
Why
Numeric enums compile to a bidirectional object: { 0: 'Active', Active: 0 }. This reverse mapping allows Status[0] === 'Active', but it also means the full object exists at runtime. String enums don't have reverse mapping. Union types have zero runtime cost.
Gotchas
- const enum is erased at compile time — can't use Object.values() on it
- String enums don't have reverse mapping and are safer than numeric
- isolatedModules (used by babel/esbuild) forbids const enum across files
- Union types work with exhaustive switch checks (never type)
Code Snippets
Alternatives to enums
// Prefer union types
type Color = 'red' | 'green' | 'blue';
// Or const object for runtime access
const Color = { Red: 'red', Green: 'green', Blue: 'blue' } as const;
type Color = typeof Color[keyof typeof Color];Context
When choosing between enums and union types in TypeScript
Revisions (0)
No revisions yet.