Hone logo
Hone
Problems

Type-Safe State Management with Discriminated Unions in TypeScript

Type-state programming allows you to represent application state using TypeScript's type system, ensuring type safety and improving code maintainability. This challenge focuses on implementing a simple state management system using discriminated unions to enforce type safety across state transitions. You'll define a set of possible states, their associated data, and functions to transition between them, all while leveraging TypeScript's type system to prevent errors.

Problem Description

You are tasked with creating a type-safe state management system for a simple counter application. The application can be in one of three states: Loading, Success, or Error. Each state has its own associated data:

  • Loading: No data associated.
  • Success: Contains a count property of type number.
  • Error: Contains an error property of type string.

You need to define a State type using a discriminated union, implement functions to transition between these states, and ensure that the transitions are type-safe. Specifically, you must:

  1. Define a State type as a discriminated union of Loading, Success, and Error types. Each variant should have a unique type property (string literal type) for discrimination.
  2. Implement a transition function that takes the current state and a transition type as input and returns a new state of the appropriate type. The transition types are: Load, Increment, Decrement, and Fail.
  3. Ensure that the transition function enforces type safety. For example, you should not be able to transition from a Loading state to a Success state directly using the Increment transition.
  4. Provide initial state and a function to display the current state.

Examples

Example 1:

Input:
  - Initial State: Loading
  - Transition: Load
Output:
  - State: Success { count: 0 }
Explanation: Starting from Loading, the Load transition moves the state to Success with an initial count of 0.

Example 2:

Input:
  - Current State: Success { count: 5 }
  - Transition: Increment
Output:
  - State: Success { count: 6 }
Explanation: Incrementing the Success state increases the count by 1.

Example 3:

Input:
  - Current State: Success { count: 10 }
  - Transition: Fail
Output:
  - Error: Error { error: "Simulated Error" }
Explanation: Transitioning to Fail from Success results in an Error state with a predefined error message.

Constraints

  • The type property of each state variant must be a string literal type.
  • The transition function must be type-safe, preventing invalid state transitions.
  • The count property in the Success state must be a non-negative integer.
  • The error property in the Error state must be a string.
  • The Load transition should always move the state to Success with a count of 0.
  • The Increment and Decrement transitions are only valid for the Success state.
  • The Fail transition can be applied to any state, resulting in an Error state.

Notes

  • Consider using conditional types to enforce type safety within the transition function.
  • The transition function should return a new state object, rather than modifying the existing one (immutability).
  • Think about how to handle invalid transitions gracefully (e.g., by returning the current state unchanged or throwing an error).
  • The goal is to demonstrate a clear understanding of discriminated unions and their application to type-safe state management. Focus on type safety and clarity over complex logic.
  • You don't need to implement a full-fledged state management library; this is a focused exercise on type-state programming.
Loading editor...
typescript