← Back to TypeScript Course | Chapter 19: Enums Deep Dive | Lesson 5 of 6

Enum vs Union Types

Enums create named values with a runtime representation, while union types describe a set of allowed values at the type level. For many modern TypeScript applications, literal unions are simpler when no runtime enum object is needed.

Enum and Union Basics

Both enums and union types can restrict a value to a known set of options, but they work fundamentally differently once you get past the type-checking stage and into actual runtime behavior.

Example: Enum and Union Basics

typescript
enum StatusEnum { Pending, Done }
type StatusUnion = "pending" | "done";
const a: StatusEnum = StatusEnum.Pending;
const b: StatusUnion = "pending";
console.log(a, b);

Runtime Differences

A normal enum emits a real JavaScript object at runtime that you could inspect or log, while a union type is a purely compile-time construct that disappears entirely once TypeScript compiles down to JavaScript.

Example: Runtime Differences

typescript
enum StatusEnum { Pending, Done }
console.log(StatusEnum); // a real object exists at runtime
type StatusUnion = "pending" | "done";
const b: StatusUnion = "pending"; // no runtime trace of the type itself
console.log(b);

Function Parameters

Both approaches restrict function arguments to a known set of values equally well at the type-checking level — the difference only shows up in what, if anything, exists once the code actually runs.

Example: Function Parameters

typescript
enum StatusEnum { Pending, Done }
type StatusUnion = "pending" | "done";
function handleEnum(s: StatusEnum) { return s; }
function handleUnion(s: StatusUnion) { return s; }
console.log(handleEnum(StatusEnum.Done), handleUnion("done"));

When Unions Are Simpler

A literal union (like "pending" | "done" | "failed") is often the simpler choice for a small, fixed set of string values when you don't need a runtime object or any enum-specific behavior like reverse mapping.

Example: When Unions Are Simpler

typescript
type Status = "pending" | "done" | "failed";
function label(status: Status) {
  return `Status: ${status}`;
}
console.log(label("pending"));

When Enums Are Useful

Enums earn their keep when you need named members backed by a shared runtime object, or when numeric values genuinely matter to how the application behaves — situations a union type alone can't provide.

Example: When Enums Are Useful

typescript
enum HttpStatus {
  Ok = 200,
  NotFound = 404,
}
function isSuccess(status: HttpStatus) {
  return status === HttpStatus.Ok;
}
console.log(isSuccess(HttpStatus.Ok));
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.