TypeScript

TypeScript Enums: When to Use Them and When to Avoid Them

An enum gives names to a set of constants. Instead of scattering magic strings or numbers across your codebase, you define them once and reference them ev...

23 Apr 2024

TypeScript Enums: When to Use Them and When to Avoid Them

Enums are one of the first features people reach for in TypeScript, and one of the first that experienced teams start banning. Both reactions are right, for different reasons. Here is the staff-level view: what enums actually compile to, where they bite, and what to use instead.

What a normal enum compiles to

Unlike most of TypeScript, a plain enum is not erased at compile time. It emits real JavaScript:

Typescript
enum Direction {
  Up,
  Down,
}

becomes an IIFE that builds a two-way lookup object:

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

That reverse mapping (Direction[0] === "Up") is occasionally useful and usually just weight your bundle carries for no reason. It is also why enums cannot be tree-shaken away when unused.

The runtime-erasure problem

This is the big one in 2026. Node.js can now run TypeScript directly by stripping types, and the same "type-stripping" approach powers fast tools across the ecosystem. Type stripping only works if every TypeScript construct can be erased without changing runtime behavior. A normal enum emits code, so it cannot be stripped. TypeScript added the erasableSyntaxOnly flag precisely to forbid enums (and other code-emitting constructs) so your project stays compatible with type-stripping runtimes.

If you want your code to run under node --experimental-strip-types or its stable successor, plain enums are a liability.

const enums do not fix it

const enum inlines its values and emits nothing:

Typescript
const enum Size { Small, Large }
const s = Size.Large; // compiles to: const s = 1;

Smaller output, but it breaks in other ways: it requires whole-program knowledge, so it fails under isolated-module compilation (Babel, esbuild, swc, and again type stripping) unless you enable extra flags, and it cannot cross a package boundary safely. Most style guides ban const enum for exactly this reason.

What to use instead

A union of string literals covers the majority of cases with zero runtime footprint:

Typescript
type Direction = "up" | "down";

function move(d: Direction) { /* ... */ }
move("up"); // autocompletes, type-checks, emits nothing

A const object with a derived type when you need a named, iterable set of values:

Typescript
const Direction = {
  Up: "up",
  Down: "down",
} as const;

type Direction = (typeof Direction)[keyof typeof Direction]; // "up" | "down"

You get the ergonomics people actually wanted from enums: a Direction.Up reference, iterable keys via Object.values(Direction), and a precise union type, but it is a plain object that tree-shakes and erases cleanly.

When an enum is still fine

This is not an absolute ban. If you are shipping an application (not a library), compiling with tsc, and not targeting a type-stripping runtime, enums are convenient and the downsides are theoretical. The rules that matter:

  • Libraries: avoid enums in your public API. A consumer using esbuild or type stripping should not inherit your compilation constraints.
  • Apps targeting type stripping: turn on erasableSyntaxOnly and use unions or const objects.
  • Everywhere: prefer string enums over numeric ones if you do use them, so values are stable and debuggable, and never rely on the numeric reverse mapping.

Wrapping up

The reason enums feel wrong to experienced TypeScript engineers is that they violate the language's core promise: types disappear at runtime, enums do not. In 2026, with type-stripping runtimes becoming the norm, that gap turned from a style opinion into a compatibility issue. Reach for a string-literal union first, a const object when you need a value bag, and keep enums out of anything you publish.

Go further
Live cohort on Maven

From Senior to Staff: Master the Architecture Skills That Get You Promoted

Go from shaky in design reviews to the engineer everyone trusts to architect the hard stuff.

View the live cohort

Keep reading