๐Ÿ“ String Enums

TypeScript Fundamentals โ€” Enums & Literal Types
TypeScript Fundamentals
Course 1 ยท Chapter 9 ยท Enums & Literal Types

๐Ÿ“ฆ Enums & Literal Types

Enums and literal types let you restrict values to a specific set of allowed options. This chapter covers string enums, numeric enums, const enums, and how literal types offer a modern alternative. You'll learn when to use each approach.

๐Ÿ“ String Enums

Basic String Enum

enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT" } function move(direction: Direction) { console.log(`Moving ${direction}`); } move(Direction.Up); // โœ… "Moving UP" move("UP"); // โŒ Error! String literal not allowed

Enum Without Explicit Values

If you don't specify values, TypeScript uses the member name:

enum Status { Active, // value is "Active" Inactive, // value is "Inactive" Pending // value is "Pending" } const status: Status = Status.Active; console.log(status); // "Active"

๐Ÿ”ข Numeric Enums

// Numeric enums auto-increment enum Level { Low = 0, Medium = 1, High = 2 } // Or let TypeScript auto-increment enum Priority { Low, // 0 Medium, // 1 High // 2 } // You can also start at any number enum HttpStatus { OK = 200, NotFound = 404, ServerError = 500 }

Reverse Mapping (Numeric Enums Only)

With numeric enums, you can look up the name from the value:

enum Status { Active = 0, Inactive = 1 } // Forward mapping: Status.Active โ†’ 0 console.log(Status.Active); // 0 // Reverse mapping: 0 โ†’ "Active" console.log(Status[0]); // "Active" const code: number = 0; console.log(Status[code]); // "Active"

โšก Const Enums

Const enums are optimized for performance. TypeScript inlines the values at compile-time, so the enum object never exists at runtime.
const enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT" } function move(direction: Direction) { console.log(direction); } move(Direction.Up); // Compiled JavaScript: // function move(direction) { console.log(direction); } // move("UP"); // Notice: Direction enum disappears! The value "UP" is inlined.
โœ… Key Benefit of Const Enums: Smaller JavaScript bundle size. The enum object is eliminated during compilation.

๐Ÿ’Ž Literal Types

A literal type is a type that is exactly one specific value. TypeScript has literal types for strings, numbers, and booleans.

String Literal Types

type Size = "small" | "medium" | "large"; function setSize(size: Size) { console.log(`Size: ${size}`); } setSize("small"); // โœ… setSize("large"); // โœ… setSize("huge"); // โŒ Error! Not in the union

Number Literal Types

type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6; function rollDice(roll: DiceRoll) { console.log(`You rolled: ${roll}`); } rollDice(3); // โœ… rollDice(7); // โŒ Error! 7 is not 1-6

Boolean Literal Types

type OnOrOff = true | false; // This is actually just boolean, but you can be more specific: type Enabled = true; // Only true is allowed function enable(status: Enabled) { // status can only be true } enable(true); // โœ… enable(false); // โŒ Error!

๐Ÿค” Enums vs Literal Types

Both can represent restricted values. Which should you use?

Feature Enum Literal Union
Syntax enum Direction { Up, Down } type Direction = "Up" | "Down"
Values Can be numbers or strings Usually strings (but can be numbers)
Reverse Mapping Yes (for numbers) No
Const Enum Optimization Yes, zero runtime overhead Already zero overhead
When to Use Legacy code, reverse mapping needed Modern code, most new projects
โœ… Modern Best Practice: Use literal types (string unions) instead of enums. They're simpler and produce the same JavaScript.

๐ŸŒ Real-World Patterns

HTTP Status Codes

// Using const enum const enum HttpStatus { OK = 200, Created = 201, BadRequest = 400, Unauthorized = 401, NotFound = 404, ServerError = 500 } function handleResponse(status: HttpStatus) { switch (status) { case HttpStatus.OK: console.log("Success"); break; case HttpStatus.NotFound: console.log("Not found"); break; } }

Event Types with Literal Union

type Event = | { type: "click"; x: number; y: number } | { type: "scroll"; delta: number } | { type: "keypress"; key: string }; function handleEvent(event: Event) { switch (event.type) { case "click": console.log(`Clicked at ${event.x}, ${event.y}`); break; case "scroll": console.log(`Scrolled ${event.delta}px`); break; case "keypress": console.log(`Pressed ${event.key}`); break; } }

๐Ÿ’ป Coding Challenges

Challenge 1: String Enum

Create a Color enum with at least 5 colors (Red, Green, Blue, Yellow, Purple). Write a function that accepts a color and returns a CSS color code.

  • Define the enum with string values
  • Create a function that maps colors to hex codes
  • Test with all colors

Goal: Practice string enums and mapping to values.

โ†’ Solution

Challenge 2: Literal Type Union

Create a LogLevel type using literal union that represents log levels: "debug", "info", "warn", "error". Write a logger function that outputs with appropriate formatting.

  • Define literal union type
  • Create logger with different prefixes per level
  • Demonstrate exhaustiveness checking

Goal: Practice literal types and discriminated unions.

โ†’ Solution

Challenge 3: Const Enum Optimization

Create a UserRole const enum with Admin, User, Guest. Build a permission checker that uses the const enum. Compare compile output with regular enum.

  • Define const enum
  • Create hasPermission function
  • Understand compile-time inlining

Goal: Understand const enum optimization and when to use it.

โ†’ Solution

๐Ÿ“‹ Best Practices

๐Ÿ’ก Use Literal Unions Over Enums

Modern TypeScript code prefers literal unions (string | unions). They're simpler, produce the same output, and work better with type inference.

// โœ… Better type Status = "active" | "inactive" | "pending"; // โŒ Legacy enum Status { Active = "active", Inactive = "inactive", Pending = "pending" }
โšก Use Const Enums for Optimization

If you must use enums, use const enum for zero runtime overhead. The values are inlined during compilation.

๐ŸŽฏ What's Next

We've mastered constants and restricted types. Chapter 10 covers Modules & Namespaces โ€” how to organize code into reusable, maintainable modules and manage scope effectively.