Enums

September 11, 20255 min read
Requirements:
FunctionsObjects| Unions

Enums in TypeScript: When and How to Use Them

Enums in TypeScript can look mysterious if you come from a JavaScript background. You might be used to juggling strings or numbers for states, and then suddenly see the enum keyword producing objects you did not expect. Are enums a superpower for cleaner code or just a quirky feature to ignore? Let's walk through what they are, why they exist, and how to use them well.

Why enums matter

In real projects you often deal with a fixed set of options. Think user roles, network request states, or days of the week. Without enums you end up with “magic strings” sprinkled through the codebase which leads to typos and invalid values slipping in at runtime. Enums group these options into a single, named collection. That makes code easier to read and safer to change.

An everyday analogy helps. Imagine a coffee shop with only three cup sizes: Small, Medium, and Large. If someone tries to order an Extra Large, the system should reject it because that option does not exist. Enums give you that same guardrail in code.

Numeric vs string enums

TypeScript gives you two main flavors: numeric and string.

enum Direction {
  Up, // 0
  Down, // 1
  Left, // 2
  Right, // 3
}

These are useful when the values themselves do not matter, only that they are distinct.

enum ResponseStatus {
  Success = 'SUCCESS',
  Failure = 'FAILURE',
  Pending = 'PENDING',
}

String enums are easier to debug because the value carries meaning without looking up a number. Many developers favor them for readability.

Practical use cases

Enums shine in three kinds of situations:

1. Application state

Example:

enum RequestState {
  Idle = 'IDLE',
  Loading = 'LOADING',
  Success = 'SUCCESS',
  Error = 'ERROR',
}

Using this enum means your state is limited to those four valid options.

2. Status codes

With HTTP responses you can make intent clearer:

enum HttpStatus {
  OK = 200,
  NotFound = 404,
  InternalError = 500,
}

Calling handleResponse(HttpStatus.OK) is more obvious than handleResponse(200).

3. Named constants

Any configuration or set of options benefits from enums. For instance, directions in a game or difficulty levels.

Const enums

TypeScript also has const enum. These do not exist at runtime at all. Instead, the compiler replaces uses with the raw values. This makes the code smaller and faster but you lose the ability to iterate over members or inspect them. Use const enums only inside your own project when you really want that performance edge.

How enums work at runtime

Unlike type aliases or interfaces, enums exist at runtime. TypeScript compiles them into JavaScript objects. Numeric enums create both forward and reverse mappings so you can get the name from a number, though relying on that trick is usually an anti pattern. String enums produce cleaner objects with only the key value pairs. Since enums exists at runtime they have some drawbacks. Check out this video by Matt Pocock for more details on the downsides of enums.

Enums vs union types

A common alternative is using a union of string literals:

type DirectionLiteral = 'Up' | 'Down' | 'Left' | 'Right'

This has no runtime cost and still gives you type safety. Many in the community prefer this pattern or the as const object approach because it stays closer to plain JavaScript. Enums are still useful when you want an actual object to exist at runtime.

Common mistakes

Watch out for these pitfalls:

A micro utility that often helps is writing a type guard. For example:

const isFruit = (value: string): value is Fruits =>
  Object.values(Fruits).includes(value as Fruits)

This ensures an incoming string really is one of the enum's values before you trust it.

Wrap up

Enums in TypeScript are a structured way to handle sets of related constants. They improve readability and help prevent errors, but they also come with quirks. Enums are great to organize your data and reuse them across your codebase.

Use union types when you only need type safety without extra JavaScript and only have a small set of values. The key is to be intentional and pick the right tool for your context.

Have you run into any tricky enum bugs or clever enum patterns in your own projects? Share them with us! We would love to hear how you handle fixed sets of values in TypeScript.

Share this article

Stay Updated

Get the latest TypeScript tips, tutorials, and course updates delivered straight to your inbox.

No spam, unsubscribe at any time.