Why I Don’t Use TypeScript Enums (And You Might Not Want To Either)

Why I Don’t Use TypeScript Enums (And You Might Not Want To Either)
Photo by Tom Brown / Unsplash

Over the years of working with TypeScript, I've found myself avoiding one particular feature—not because it's broken or doesn't work, but because it just feels wrong in modern, maintainable JavaScript codebases. That feature is enum.

Now don’t get me wrong: TypeScript enums do work. But if you're aiming for clean, predictable, and portable code, here’s why I think enums are better left out of most projects—and what I use instead.


🧠 1. WYSIWYG: What You See Is What You Get

When I write TypeScript, I want it to feel like a typed version of JavaScript—not some black box that hides complex output. And here’s the problem:

enum Direction {
  Up,
  Down
}

This compiles to:

var Direction;
(function (Direction) {
  Direction[Direction["Up"] = 0] = "Up";
  Direction[Direction["Down"] = 1] = "Down";
})(Direction || (Direction = {}));

That’s not WYSIWYG. What looked like a clean declaration has now become a bidirectional object with numeric values and extra runtime logic. And you don’t realize this until something breaks or bloats your bundle.

In contrast, if you define directions like this:

const Direction = {
  Up: 'Up',
  Down: 'Down'
} as const;

type Direction = (typeof Direction)[keyof typeof Direction];

It stays exactly as you wrote it. No surprises, no hidden JS. That’s what modern TypeScript should feel like.


🌍 2. Portability Matters

One of my key principles is: write once, run anywhere. But enums introduce friction here too.

  • const enum won’t work unless your build tool fully supports TypeScript’s emit behavior (and many don’t).
  • Regular enum creates a runtime object, which means interoperability with JS becomes messy, especially in Node environments or mixed JS/TS codebases.
  • Tools like Babel and SWC don’t always handle enums gracefully, which limits how flexible your environment setup can be.

This makes enums a fragile abstraction in the context of modern JavaScript tooling.


🗣 3. The TypeScript Team Wouldn’t Add Them Today

This one sealed the deal for me. Multiple TypeScript maintainers have said that if enums were proposed today, they wouldn’t be added to the language.

In fact, TypeScript has evolved toward promoting string union types + as const objects as the better alternative. These patterns are:

  • Fully type-safe
  • Intuitive
  • Runtime-compatible
  • Tree-shakeable

If the maintainers themselves don’t love enums, that’s a big signal to steer away from them.


🛠 4. Alternatives Are Better in Every Way

The main use case for enums is giving a list of named constants. But TypeScript gives you cleaner, safer, and more idiomatic ways to do that:

const Status = {
  Draft: 'draft',
  Published: 'published',
  Archived: 'archived'
} as const;

type Status = typeof Status[keyof typeof Status];

This gives you type safety, IDE autocomplete, and runtime predictability—without the enum baggage.


⚠️ Other Considerations

  • Serialization: Enums can create problems when sending data over the network. The reverse mapping (e.g., Status[1]) often leads to bugs if the server expects a string, not a number.
  • Debugging: Since enums emit objects at runtime, they can bloat logs and stack traces with content that doesn’t match your source code.
  • Refactoring: Unlike plain objects or union types, enums can’t be partially tree-shaken or optimized in the same way—renaming an enum member has broader implications.

✅ TL;DR – Why I Avoid Enums

  • They generate non-obvious JavaScript
  • They don’t always work across platforms or tools
  • They are not recommended by the TS team anymore
  • String unions + as const objects are cleaner, safer, and more portable

🔁 Finally

Enums aren’t “bad”. But TypeScript is no longer what it was when enums were first introduced. The ecosystem, tooling, and best practices have evolved—and sticking with enums now feels like choosing legacy patterns in a modern codebase.

If you value clarity, consistency, and future-proofing, you probably don’t need enums anymore. And honestly? You won’t miss them.

Support Us