TypeScript Enums: 5 Real-World Use Cases
Tags: typescript, webdev, javascript, programming
Published: 2024-03-12 01:29:40

If you’re looking to make your TypeScript code more organized, enums are a powerful tool. They group related values together, giving your code better structure and readability. Let’s dive in and explore how to use them!

In TypeScript, enums are declared using the `enum` keyword. For example, you could create an enum to represent the different fruit prices as follows:

## Example 1: Basic Enum Structure — Key Movements

Demonstrates a common use case for enums: making choices within a limited set clearer.

```typescript
enum Movement {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT"
}

function handlePlayerInput(key: string) {
  switch (key) {
    case Movement.Up:
     // Move player character up
      break;
    case Movement.Down:
      // Move player character down
      break;
    // ... other cases
  }
}
```

This demonstrates the fundamental syntax for defining an enum. The `Movement` enum has four members representing directions.

## Example 2: Enums with Values

Enums can have associated values (numbers, strings, etc.). Here, `StatusCode` associates HTTP status codes, ensuring type-safety and preventing the use of arbitrary numbers.

```typescript
enum StatusCode {
  OK = 200,
  BadRequest = 400,
  NotFound = 404
}

function handleResponse(code: StatusCode) {
  if (code === StatusCode.OK) {
    // Handle successful response
  } else if (code === StatusCode.NotFound) {
    // Handle resource not found
  } 
  // ... other cases
}
```


![HTTP status codes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19dr3ztmspzsc43fflzf.png)

Image source: [https://restfulapi.net/http-status-codes](https://restfulapi.net/http-status-codes/)

## Example 3: Enum from Redux Toolkit

Redux Toolkit is a popular library for state management in React applications. It makes heavy use of TypeScript for type safety.


![Redux logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o2rle1vdipn595j86z0j.png)


This enum defines distinct states for asynchronous actions (like fetching data). This is common in state management libraries.

```typescript
enum PayloadActionLoadingState {
  Idle = "idle",
  Loading = "loading",
  Failed = "failed",
  Success = "success" 
}
```

## Example 4: Enum as a Discriminated Union

This enum defines two possible shapes: `Circle` and `Rectangle`. It acts as a foundation for ensuring type safety when working with different shapes.

Each shape type (`Circle`, `Rectangle`) is represented as a member of the `ShapeType` enum.

The `Shape` interface has a `type` property that must be a member of the `ShapeType` enum.

```typescript
enum ShapeType {
    Circle = "Circle",
    Rectangle = "Rectangle"
  }
  
  interface Shape {
    type: ShapeType; 
  }
  
  interface Circle extends Shape {
    type: ShapeType.Circle;
    radius: number;
  }
  
  interface Rectangle extends Shape {
    type: ShapeType.Rectangle;
    width: number;
    height: number;
  }
  
  function calculateArea(shape: Shape): number {
    switch (shape.type) {
      case ShapeType.Circle:
        const circle = shape as Circle; // Type assertion to Circle
        return Math.PI * circle.radius * circle.radius;
      case ShapeType.Rectangle:
        const rectangle = shape as Rectangle; // Type assertion to Rectangle
        return rectangle.width * rectangle.height;
      default:
        throw new Error("Invalid shape type");
    }
  }
```

Specific shape interfaces (`Circle`, `Rectangle`) extend the base `Shape` interface and must have their `type` property set to the corresponding enum value.

This lets the `calculateArea` function use the `type` property as a discriminator to determine the appropriate calculation.

## Example 5: Enums as Data Structures

This TypeScript code defines a simple model for representing playing cards, focusing on the suits, ranks, and the color of the card, which is derived from its suit.

It consists of two enums, a function to get a card’s numerical value, an interface to describe a card’s structure, and a function to create a card.

```typescript
enum Suit {
  Hearts = "♥", // Red suit
  Diamonds = "♦", // Red suit
  Clubs = "♣", // Black suit
  Spades = "♠" // Black suit
}

enum Rank {
  Ace = 1,
  Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten,
  Jack, Queen, King 
}

function getCardValue(rank: Rank): number {
  if (rank <= Rank.Ten) {
    return rank;
  } else {
    return 10;
  }
}

interface Card {
  suit: Suit;
  rank: Rank;
  color: string; // Derived property based on suit
}

function createCard(suit: Suit, rank: Rank): Card {
  return {
    suit,
    rank,
    color: suit === Suit.Hearts || suit === Suit.Diamonds ? 'Red' : 'Black'
  }
}

// Usage
let card1 = createCard(Suit.Hearts, Rank.Ace);
console.log(`The Ace of Hearts is red: ${card1.color}`); // Output: The Ace of Hearts is red: Red

let card2 = createCard(Suit.Spades, Rank.Queen);
console.log(`The Queen of Spades is black: ${card2.color}`); // Output: The Queen of Spades is black: Black
```

Function `getCardValue` takes a `Rank` as an argument and returns a number. For ranks `Ace` through `Ten` (numerically 1 to 10), it returns the rank's numeric value. For face cards (`Jack`, `Queen`, `King`), which have rank values greater than 10, it returns 10.

Two card objects are created using the `createCard` function:  `card1` as the Ace of Hearts (which is red) and `card2` as the Queen of Spades (which is black).

This code is a straightforward way to model the basic properties of playing cards in a type-safe manner using TypeScript’s features like enums, interfaces, and type inference.

## Conclusion

Enums provide a solid foundation for clean and structured TypeScript code. As your projects grow in complexity, their benefits will continue to shine.

TypeScript enums are a powerful tool to elevate your code. They enhance readability, maintainability, and type safety.

Check out my other TypeScript articles:
- [TypeScript Index Signatures: 4 Examples Type-Safe Dynamic Objects](https://dev.to/alexefimenko/typescript-index-signatures-4-examples-type-safe-dynamic-objects-554o)
- [Making React Components More Flexible with TypeScript Generics: 3 Examples](https://dev.to/alexefimenko/3-examples-of-typescript-generic-react-components-4f9)
- [5 Resources Each TypeScript Developer Should Know About](https://dev.to/alexefimenko/5-resources-each-typescript-developer-should-know-about-30m4)

This article was originally [posted on Medium](https://medium.com/@alexefimenko/typescript-enums-5-real-world-use-cases-7ceccc423c18).