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 acountproperty of typenumber.Error: Contains anerrorproperty of typestring.
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:
- Define a
Statetype as a discriminated union ofLoading,Success, andErrortypes. Each variant should have a uniquetypeproperty (string literal type) for discrimination. - Implement a
transitionfunction 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, andFail. - Ensure that the
transitionfunction enforces type safety. For example, you should not be able to transition from aLoadingstate to aSuccessstate directly using theIncrementtransition. - 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
typeproperty of each state variant must be a string literal type. - The
transitionfunction must be type-safe, preventing invalid state transitions. - The
countproperty in theSuccessstate must be a non-negative integer. - The
errorproperty in theErrorstate must be a string. - The
Loadtransition should always move the state toSuccesswith a count of 0. - The
IncrementandDecrementtransitions are only valid for theSuccessstate. - The
Failtransition can be applied to any state, resulting in anErrorstate.
Notes
- Consider using conditional types to enforce type safety within the
transitionfunction. - The
transitionfunction 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.