Skip to content

Expose per-state schemas on machine state nodes - #5617

Merged
davidkpiano merged 1 commit into
statelyai:nextfrom
asfktz:fix/per-state-schemas-on-machine
Jul 31, 2026
Merged

Expose per-state schemas on machine state nodes#5617
davidkpiano merged 1 commit into
statelyai:nextfrom
asfktz:fix/per-state-schemas-on-machine

Conversation

@asfktz

@asfktz asfktz commented Jul 30, 2026

Copy link
Copy Markdown

Problem

setup() lets you declare schemas for individual states, but they never made it onto the compiled machine. Only the root-level schemas were merged in — anything declared under states was silently dropped:

import { setup, types } from 'xstate';

const machine = setup({
  states: {
    running: {
      schemas: {
        context: types<{ startedAt: number }>()
      }
    }
  }
}).createMachine({
  initial: 'running',
  states: {
    running: {}
  }
});

machine.states.running.schemas; // ❌ was undefined

This meant tooling that only has access to the machine (e.g. a per-state snapshot validator, docs generation, serialization) couldn't see the per-state schemas at all — they were only reachable through the setup() return value.

Fix

createMachine now recursively merges the setup states schema tree into the machine config, and StateNode exposes a schemas property:

machine.states.running.schemas?.context; // ✅ the schema you declared
machine.states.running.states.child.schemas; // ✅ works for nested states too

Merge rules follow the existing root-level behavior: setup schemas win over inline config schemas, and setup states with no matching config state are ignored.

Notes

  • machine.states.X.schemas is typed as the loose SetupStateSchemas ({ context?; input? }), not the precise declared schema types. Narrowing it is a possible follow-up.
  • Next_MachineConfig now omits schemas from the state-node config it extends, so the new per-state field doesn't collide with the machine-level schemas option (no change to the public createMachine surface).

@changeset-bot

changeset-bot Bot commented Jul 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4d85b8c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
xstate Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@davidkpiano
davidkpiano merged commit d9d9e29 into statelyai:next Jul 31, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants