effect-state-machine
How-to guides

Choose transitions with guards

Select ordered transition branches and declare intentional no-op events.

This guide shows you how to choose among several transitions for one event and how to accept an event without changing state.

Add ordered guard branches

Replace a direct transition with branches. Guard branches are checked from top to bottom; the first matching branch wins:

const isPositive = classifier.guard<{
  readonly event: { readonly _tag: "Decide"; readonly value: number }
}>({
  name: "is-positive",
  description: "Positive values take precedence.",
  guard: ({ event }) => event.value > 0,
})

const ready = classifier.state({
  Decide: {
    branches: [
      {
        when: isPositive,
        target: "Positive",
        reduce: ({ event }) => ({ value: event.value }),
      },
      {
        when: {
          name: "is-even",
          description: "Non-positive even values use the Even state.",
          guard: ({ event }) => event.value % 2 === 0,
        },
        target: "Even",
        reduce: ({ event }) => ({ value: event.value }),
      },
      {
        otherwise: true,
        target: "Other",
        reduce: ({ event }) => ({ value: event.value }),
      },
    ],
  },
})

Use machine.guard when you want source-location metadata to point to a separately declared guard. An inline when object remains valid when the decision belongs beside the transition.

Keep the otherwise branch last. If no guard matches and no fallback exists, sending the event terminates the instance with ProtocolDefect.

Accept an intentionally irrelevant event

Declare an ignored event explicitly:

const ready = classifier.state({
  Ping: {
    ignore: {
      description: "Heartbeats do not affect classification.",
    },
  },
})

For an ignored event, can(event) returns true, send(event) succeeds, the snapshot does not change, and the inspection stream emits EventIgnored.

Inspect the decisions

Use Decide 5, Reset, Decide -4, and Reset to compare the ordered guard branches. Select Ignore Ping while Ready is active to see the ignored event recorded without a state change. Guard descriptions appear beneath their names on the transition cards.

Starting the classifier machine…

The goal is complete when every globally known event received by the state is either routed or explicitly ignored. See the generated Machine API for the complete transition shapes.

On this page