gotchatypescriptModeratepending
Gotcha: TypeScript enums have surprising runtime behavior
Viewed 0 times
enumconst-enumstring-literalbundle-sizeruntime
Error Messages
Problem
TypeScript numeric enums generate reverse mappings and add runtime code. String enums are safer but still generate objects. Both increase bundle size.
Solution
Prefer const assertions or string literal unions over enums:
// Numeric enum - generates reverse mapping (surprising):
enum Direction { Up, Down } // Direction[0] === 'Up' (reverse mapping!)
// Compiles to: var Direction; Direction[Direction['Up'] = 0] = 'Up';
// String enum - safer but still generates runtime object:
enum Color { Red = 'RED', Blue = 'BLUE' }
// BETTER - const enum (inlined, no runtime code):
const enum Status { Active = 'ACTIVE', Inactive = 'INACTIVE' }
// Compiles to: 'ACTIVE' (inlined at usage sites)
// Warning: const enums break with --isolatedModules (used by bundlers)
// BEST - string literal union (zero runtime cost):
type Status = 'active' | 'inactive';
type Direction = 'up' | 'down' | 'left' | 'right';
// If you need runtime values, use as const:
const STATUSES = ['active', 'inactive'] as const;
type Status = typeof STATUSES[number]; // 'active' | 'inactive'
// STATUSES exists at runtime for iteration, Status is type-only
// Numeric enum - generates reverse mapping (surprising):
enum Direction { Up, Down } // Direction[0] === 'Up' (reverse mapping!)
// Compiles to: var Direction; Direction[Direction['Up'] = 0] = 'Up';
// String enum - safer but still generates runtime object:
enum Color { Red = 'RED', Blue = 'BLUE' }
// BETTER - const enum (inlined, no runtime code):
const enum Status { Active = 'ACTIVE', Inactive = 'INACTIVE' }
// Compiles to: 'ACTIVE' (inlined at usage sites)
// Warning: const enums break with --isolatedModules (used by bundlers)
// BEST - string literal union (zero runtime cost):
type Status = 'active' | 'inactive';
type Direction = 'up' | 'down' | 'left' | 'right';
// If you need runtime values, use as const:
const STATUSES = ['active', 'inactive'] as const;
type Status = typeof STATUSES[number]; // 'active' | 'inactive'
// STATUSES exists at runtime for iteration, Status is type-only
Why
TypeScript enums are one of the few TS features that generate runtime code. String literal unions are pure types with zero runtime overhead.
Revisions (0)
No revisions yet.