DEV Community

Cover image for Stop blindly replacing `enum` with `as const`
Kelvyn Thai
Kelvyn Thai

Posted on

Stop blindly replacing `enum` with `as const`

You’ve probably seen many posts suggesting that we should replace TypeScript enum with as const objects because of benefits like:

  • better tree-shaking
  • smaller bundle size
  • less runtime code

That advice is not entirely wrong, but it is often oversimplified.

The real question is not “Should we stop using enums?”
The better question is:

Do we actually understand what TypeScript generates behind the scenes, and what trade-offs we are making?

The key idea: reverse mapping

For numeric enums, TypeScript generates extra runtime code.

enum Direction {
  Up,
  Down,
  Left,
  Right,
}
Enter fullscreen mode Exit fullscreen mode

This is transpiled to JavaScript roughly like this:

var Direction;
(function (Direction) {
  Direction[Direction["Up"] = 0] = "Up";
  Direction[Direction["Down"] = 1] = "Down";
  Direction[Direction["Left"] = 2] = "Left";
  Direction[Direction["Right"] = 3] = "Right";
})(Direction || (Direction = {}));
Enter fullscreen mode Exit fullscreen mode

At first glance, that looks weird.
But here is what is happening:

  1. TypeScript creates an IIFE (Immediately Invoked Function Expression).
  2. It assigns Direction["Up"] = 0.
  3. That assignment returns 0, so TypeScript also sets Direction[0] = "Up".

So at runtime, we get an object like this:

{
  Up: 0,
  Down: 1,
  Left: 2,
  Right: 3,
  0: "Up",
  1: "Down",
  2: "Left",
  3: "Right"
}
Enter fullscreen mode Exit fullscreen mode

This is called reverse mapping.

That means:

Direction.Up // 0
Direction[0] // "Up"
Enter fullscreen mode Exit fullscreen mode

Why some developers prefer as const

Now compare that with:

const DirectionConst = {
  Up: "Up",
  Down: "Down",
  Left: "Left",
  Right: "Right",
} as const;
Enter fullscreen mode Exit fullscreen mode

This is just a plain JavaScript object.
No IIFE.
No reverse mapping.
No extra enum runtime emit.

That is why many developers say as const can be better for:

  • frontend apps
  • config objects
  • route names
  • statuses
  • action types
  • other JS-first patterns

But does that mean enum is bad?

Not at all.

The real issue is that many people blindly replace enums without understanding the use case.

Because not all enums are the same:

  • numeric enums generate reverse mapping
  • string enums do not generate reverse mapping
  • const enum has a different trade-off again
  • as const is not a 1:1 replacement for every enum use case

The important takeaway

We should not blindly replace enum with as const just because it is trending.

Instead, we should ask:

  • Do we need reverse mapping?
  • Do we need a runtime enum object?
  • Are we using numeric enums or string enums?
  • Is this app code, library code, or protocol/compiler-style code?
  • Are we optimizing for explicitness, bundle size, or JS simplicity?

Final thought

as const is a great pattern.
But enum is not automatically wrong.

The real senior move is not to follow slogans like:

“Stop using enums.”

The real senior move is to understand how TypeScript works behind the scenes and choose the right tool for the right use case.

Top comments (0)