What are enums, and why do many teams prefer const objects with as const instead?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
Enums define named constant sets. But regular enums generate runtime JavaScript objects with quirks (reverse mapping for numeric enums, heterogeneous pitfalls), so many teams prefer as const objects + derived union types — zero runtime cost, tree-shakeable, consistent with JS.
Detailed explanation
Enum options: numeric enums auto-increment and allow reverse lookups (Direction.Up → 0, Direction[0] → 'Up'), string enums are safer and self-describing, const enums inline away but carry isolation-mode gotchas. Criticisms: enums emit code unlike anything vanilla JS produces, complicate bundler interop, permit assignments outside their members under some settings, and behave inconsistently between numeric/string variants. The modern alternative: freeze intent at the type level instead — const STATUSES = { Active: 'active', Archived: 'archived' } as const; plus type Status = (typeof STATUSES)[keyof typeof STATUSES]; gives the same named membership as a string enum with plain-object semantics. Union types alone suffice for closed sets without a namespace. Enums aren't wrong — plenty of codebases use them happily — but be ready to discuss tradeoffs rather than recite syntax.
Example
// Enum version:
enum Direction { Up, Down }
// Compiles to a live object with reverse mapping.
// Const-object version:
const Direction2 = { Up: 'up', Down: 'down' } as const;
type Direction2 = (typeof Direction2)[keyof typeof Direction2];
// 'up' | 'down' — no runtime artifact beyond the object itselfInterview tip
Show both versions side by side and mention reverse-mapping as the numeric-enum quirk. Saying 'it depends on team conventions' is a mature close.
Common mistakes
- Ignoring that numeric enums allow any number assignment historically.
- Claiming const objects replace enums only partially — they cover the main cases.