Bird
Raised Fist0
Typescriptprogramming~5 mins

Discriminated union state machines in Typescript - Cheat Sheet & Quick Revision

Choose your learning style10 modes available
Recall & Review
beginner
What is a discriminated union in TypeScript?
A discriminated union is a special type of union where each member has a common property with a unique literal type. This property helps TypeScript narrow down the type safely.
Click to reveal answer
beginner
Why use discriminated unions for state machines?
They let you clearly define each state with a unique 'tag' property, making it easy to check the current state and handle transitions safely with TypeScript's type checking.
Click to reveal answer
intermediate
Example of a discriminated union for a traffic light state machine?
type TrafficLight = | { state: 'red'; duration: number } | { state: 'yellow'; duration: number } | { state: 'green'; duration: number }; Each object has a 'state' property that discriminates the union.
Click to reveal answer
intermediate
How does TypeScript help when switching on a discriminated union?
TypeScript narrows the type inside each case block based on the discriminant property, so you get autocompletion and type safety for that specific state.
Click to reveal answer
advanced
What happens if you forget to handle a state in a discriminated union switch?
TypeScript can warn you if you use the 'never' type in a default case, helping you catch missing cases and making your state machine safer.
Click to reveal answer
What property is essential in a discriminated union to distinguish states?
AA numeric index
BA method to change states
CA common property with unique literal values
DAn optional property
In a state machine using discriminated unions, how do you typically check the current state?
AUsing if statements on random properties
BBy using a global variable
CBy checking the object's prototype
DUsing a switch statement on the discriminant property
What benefit does TypeScript provide when handling all states in a discriminated union?
AIt ensures all cases are handled, preventing runtime errors
BIt automatically fixes bugs
CIt runs the code faster
DIt hides unused states
Which of these is a valid discriminated union type for a simple state machine?
Atype State = any
Btype State = { status: 'on' } | { status: 'off' }
Ctype State = { value: number } & { value: string }
Dtype State = number | string
What TypeScript feature helps catch missing cases in a discriminated union switch?
AThe 'never' type in a default case
BThe 'any' type
CThe 'unknown' type
DThe 'void' type
Explain how discriminated unions help build safe state machines in TypeScript.
Think about how TypeScript knows which state you are working with.
You got /4 concepts.
    Describe how you would implement a simple traffic light state machine using discriminated unions.
    Focus on the 'state' property as the discriminator.
    You got /4 concepts.

      Practice

      (1/5)
      1.

      What is the main purpose of using a discriminated union in TypeScript state machines?

      easy
      A. To enable dynamic addition of states at runtime without type errors.
      B. To clearly define different states with a common type property for safe type checking.
      C. To allow any property names in the state objects without restrictions.
      D. To automatically generate UI components based on state names.

      Solution

      1. Step 1: Understand discriminated unions

        Discriminated unions use a common type property to distinguish between different object shapes.
      2. Step 2: Identify the purpose in state machines

        This common property allows TypeScript to safely narrow the state type and catch errors.
      3. Final Answer:

        To clearly define different states with a common type property for safe type checking. -> Option B
      4. Quick Check:

        Discriminated union = safe state typing [OK]
      Hint: Look for the common type property in states [OK]
      Common Mistakes:
      • Thinking discriminated unions allow any property names freely
      • Assuming states can be added dynamically without type errors
      • Confusing discriminated unions with UI generation
      2.

      Which of the following is the correct syntax to define a discriminated union type for a state machine with states loading and success?

      type State = ?
      easy
      A. { status: 'loading' } | { status: 'success'; data: string }
      B. { type: 'loading'; data: string } | { type: 'success' }
      C. { type: 'loading' } | { type: 'success'; data: string }
      D. { state: 'loading' } | { state: 'success'; data: string }

      Solution

      1. Step 1: Identify the discriminant property

        The discriminated union requires a common property named type to distinguish states.
      2. Step 2: Match the correct state shapes

        Loading state has only type: 'loading', success state has type: 'success' and extra data.
      3. Final Answer:

        { type: 'loading' } | { type: 'success'; data: string } -> Option C
      4. Quick Check:

        Common type property with correct fields = B [OK]
      Hint: Discriminant property must be named exactly 'type' [OK]
      Common Mistakes:
      • Using different property names like 'status' or 'state'
      • Mixing properties between states incorrectly
      • Adding data to loading state incorrectly
      3.

      Given the following TypeScript code, what will be the output?

      type State =
        | { type: 'idle' }
        | { type: 'loading' }
        | { type: 'success'; data: string };
      
      function getMessage(state: State): string {
        switch (state.type) {
          case 'idle':
            return 'Waiting...';
          case 'loading':
            return 'Loading...';
          case 'success':
            return `Data: ${state.data}`;
        }
      }
      
      console.log(getMessage({ type: 'success', data: 'Hello' }));
      medium
      A. Error: Property 'data' does not exist
      B. Loading...
      C. Waiting...
      D. Data: Hello

      Solution

      1. Step 1: Analyze the input state

        The input state is { type: 'success', data: 'Hello' }, matching the 'success' case.
      2. Step 2: Follow the switch case logic

        For 'success', the function returns `Data: ${state.data}`, which becomes 'Data: Hello'.
      3. Final Answer:

        Data: Hello -> Option D
      4. Quick Check:

        State 'success' returns data string [OK]
      Hint: Match type in switch to get correct output [OK]
      Common Mistakes:
      • Confusing 'success' with 'loading' or 'idle'
      • Expecting an error accessing 'data' without checking type
      • Ignoring template string interpolation
      4.

      Identify the error in this discriminated union state machine code:

      type State =
        | { type: 'start' }
        | { type: 'end'; result: number };
      
      function process(state: State) {
        if (state.type === 'start') {
          console.log('Starting');
        } else {
          console.log('Result is ' + state.result);
        }
      }
      
      process({ type: 'start' });
      medium
      A. No error; code runs and prints 'Starting'.
      B. Error: Accessing 'result' on 'start' state causes runtime error.
      C. Error: Missing return type annotation on function.
      D. Error: 'type' property should be optional.

      Solution

      1. Step 1: Check the state type conditions

        The function checks if state.type === 'start' and logs 'Starting'.
      2. Step 2: Confirm safe access to 'result'

        In the else branch, state.result is accessed only if state.type !== 'start', so it must be 'end' with result.
      3. Final Answer:

        No error; code runs and prints 'Starting'. -> Option A
      4. Quick Check:

        Type narrowing prevents invalid property access [OK]
      Hint: Check type guards before accessing state-specific properties [OK]
      Common Mistakes:
      • Assuming accessing 'result' on 'start' state causes error
      • Expecting return type annotation is mandatory
      • Thinking 'type' property should be optional
      5.

      You want to extend a discriminated union state machine to handle an error state with an optional message. Which is the best way to define this state to keep type safety and allow missing message?

      type State =
        | { type: 'idle' }
        | { type: 'loading' }
        | { type: 'success'; data: string }
        | ???
      hard
      A. { type: 'error'; message?: string }
      B. { type: 'error'; message: string | undefined }
      C. { type: 'error'; message: string }
      D. { type: 'error'; message: string | null }

      Solution

      1. Step 1: Understand optional properties in discriminated unions

        Using message?: string means the property can be missing or a string, which fits optional message.
      2. Step 2: Compare other options

        { type: 'error'; message: string | undefined } requires the property but allows undefined explicitly, less idiomatic. { type: 'error'; message: string } requires message always. { type: 'error'; message: string | null } requires message but allows null, which is less type safe.
      3. Final Answer:

        { type: 'error'; message?: string } -> Option A
      4. Quick Check:

        Optional property syntax keeps type safety and flexibility [OK]
      Hint: Use '?' to mark optional properties in state types [OK]
      Common Mistakes:
      • Making message required when it should be optional
      • Using union with undefined instead of optional property
      • Allowing null which can cause runtime issues
      Recommended

      Ready to prove it?

      Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

      10 questions~5 mineasy hard