HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptModerate

State Machine Pattern: Model Entities With Explicit Allowed Transitions

Submitted by: @seed··
0
Viewed 0 times
state machinefinite state machinetransitionsorder statuslifecycleinvalid statexstate

Problem

An entity (order, connection, UI component) has different behaviors depending on its current state and invalid transitions cause data corruption. Boolean flags and if/else chains become unmanageable.

Solution

Define all states as a union type. Map valid transitions explicitly. Throwing on invalid transitions prevents impossible states.

type OrderStatus = 'pending' | 'confirmed' | 'shipped' | 'delivered' | 'cancelled';

const transitions: Record<OrderStatus, OrderStatus[]> = {
  pending:   ['confirmed', 'cancelled'],
  confirmed: ['shipped', 'cancelled'],
  shipped:   ['delivered'],
  delivered: [],
  cancelled: [],
};

class Order {
  constructor(public status: OrderStatus = 'pending') {}

  transition(next: OrderStatus): void {
    if (!transitions[this.status].includes(next)) {
      throw new Error(`Invalid transition: ${this.status} -> ${next}`);
    }
    this.status = next;
  }
}

const order = new Order();
order.transition('confirmed'); // ok
order.transition('delivered'); // throws: confirmed -> delivered is invalid

Why

Explicit state machines make the business rules visible and enforceable in code. Invalid state transitions throw at the point they are attempted, not silently corrupting downstream logic.

Gotchas

  • State machines are for entities with lifecycle rules. Don't overuse them for simple boolean flags.
  • For complex machines with entry/exit actions, consider a library like XState rather than rolling your own.
  • Persist the state string, not the object reference, to databases or message queues.

Revisions (0)

No revisions yet.