Exercise: Model Structured API States with Discriminated Unions

Master discriminated unions by modeling a real-world API response with full exhaustiveness and type safety.

We'll cover the following...

We’ve seen how discriminated unions give us precision. Now let’s take that precision and put it to work.

The problem

We’re building a frontend that calls an API to fetch user profile data. The server doesn’t just return raw values—it sends structured responses that reflect the state of the request. This is a perfect use case for discriminated unions.

In this exercise, you’ll model those responses using a type-safe discriminated union.

The API can return one of three structured outcomes:

  1. A success response that includes:

    1. A status field with the literal value "success".

    2. A user object with:

      1. id (number).

      2. name (string).

      3. email (string).

  2. A failure response that includes:

    1. A status field with the literal value "failure".

    2. A message string explaining what went wrong.

  3. A pending response that includes:

    1. A status field with the literal value "pending".

    2. A retryAfter timestamp in milliseconds (number).

Your tasks:

  • Define a discriminated union type called ProfileApiResponse that captures all three cases above.

  • Write a function handleApiResponse(response: ProfileApiResponse): string that returns a human-readable message depending on the response type.

  • Use a switch on the discriminant (status) to narrow the type.

  • Enforce exhaustiveness with a never check in the switch statement.

  • Test your implementation with example calls for all three response types.

Good luck!