Tree-shakeable enums in Typescript-based ES modules

(, en)

NOTE: If you are in a Typescript-only codebase, you probably can just use union types instead of enums.

Typescript has enums, but this feature (currently) has its shortcomings. What? Shortcomings? Not in my code! Actually, it is more about compatibility. Typescript transpiles to JavaScript which (under usual conditions) will end up in your app and finally as bundled JS in the browser.

One frequent concern is the bundle-size of the final app. There are multiple methods to reduce the bundle size, such as minification, compression or tree-shaking. Of course you can also keep your dependency footprint small. Here I want to focus on tree shaking.

Tree shaking is a term commonly used in the JavaScript context for dead-code elimination. – webpack doc

Unfortunately, Typescript enums can prevent proper tree shaking. For now I settled for using the as const construction:

export const Fruits = {
  Banana: "Banana",
  Apple: "Apple",
  Orange: "Orange",
} as const;

// intentionally naming the variable the same as the type
// eslint-disable-next-line @typescript-eslint/no-redeclare
export type Fruits = typeof Fruits[keyof typeof Fruits];

To cite the original Typescript docs:

The biggest argument in favour of this format over TypeScript’s enum is that it keeps your codebase aligned with the state of JavaScript, and when/if enums are added to JavaScript then you can move to the additional syntax.

See also