Enums vs Const Objects

Why modern TypeScript developers are abandoning enums.

TypeScript4 min readConcept 7 of 54

The Enum debate

An enum is a feature that allows you to define a set of named constants. However, unlike most TypeScript features which disappear completely when compiled, enum actually generates real JavaScript code at runtime.

A modern alternative is to use a plain JavaScript object paired with an as const assertion. This locks the object's values so they can't be changed, providing the same type-safety as an enum but with much cleaner output.

The bundle size tax

Because enum is not a native JavaScript feature (yet), the TypeScript compiler has to transform it into a complex Immediately Invoked Function Expression (IIFE).

This adds unnecessary bulk to your JavaScript bundle. Worse, bundlers like Webpack and Rollup sometimes struggle to 'tree-shake' (remove unused parts) of enums because of how the IIFE is structured.

The modern alternative

Instead of writing this:

typescript enum Status { Pending = "PENDING", Active = "ACTIVE" }

Modern codebases write this:

typescript const Status = { Pending: "PENDING", Active: "ACTIVE" } as const; // Extract the union type of its values: type StatusType = typeof Status[keyof typeof Status];

Try it

Watch the TypeScript compiler generate JavaScript for both an enum and a const object. Notice the massive difference in output size.

// 1. The Enum approach
enum Status {
Active = "ACTIVE"
}

// 2. The const object approach
const StatusObj = {
Active: "ACTIVE"
} as const;
Compiled JavaScript Output
enum output:
as const output:
Objects are smaller and easier to tree-shake!

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1Why do some bundlers struggle to optimize (tree-shake) TypeScript enums?

Remember this

  • Enums leave a footprint in your compiled JavaScript bundle.
  • Numeric enums create confusing reverse-mappings.
  • Use as const objects for runtime constants.
  • Use string unions (type A = 'X' | 'Y') when you don't need runtime access.

Done with this concept?

Mark it complete to track your progress. No login needed.