Conversation
🦋 Changeset detectedLatest commit: 271d473 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
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 |
|
cc. @Andarist |
|
Very much needed functionality! Would it also validate below example correctly? const machine = setup({...}).createMachine({ |
|
@Andarist how can I make reviewing this PR easier? The changes are mostly all made to pass more type information such that Anything that I can do to help (description, comments, etc.)? |
|
@SandroMaglione Can you merge |
0907838 to
56c3354
Compare
Done |
|
Fyi, im in the process of reviewing this |
|
@SandroMaglione this has type issues in tests right now, could you take a look at this? |
Two additions to
createMachine's type signature:const TStates— a new type parameter that captures the literal shape of thestatesproperty via& { states?: TStates }(additive intersection,MachineConfigstays intact).ValidateConfigTargets<{ states: TStates }>— a validation type intersected into the config. It walks the state tree, extractskeyof TStates & stringas sibling keys at each level, and constrains everytargetvalue inon,always,after,onDone, andinvoke.onDone/onError/onSnapshottoValidTarget<TSiblingKeys>(sibling names,.child,#id,sibling.child, or escaped-dot variants).For
setup().createMachine, the existingconst TConfigalready captures literals — only& ValidateConfigTargets<TConfig>is added.How it works
ValidTarget<TSiblingKeys>defines valid patterns.ValidateConfigTargetsrecursively maps over the config, replacing each target position withValidTarget<siblings>. The intersection withMachineConfig(which acceptsstring) narrows targets to valid siblings. Invalid literals produce a type error; spread-widenedstringvalues pass through via astring extends T ? Tescape hatch.What the
TSiblingKeysthreading is forA
TSiblingKeys extends string = stringparameter was added toTransitionConfigOrTarget,TransitionsConfig,DelayedTransitions,InvokeConfig,StateNodeConfig,StatesConfig, andMachineConfig. All default tostring(non-breaking). These replace barestringwithValidTarget<TSiblingKeys>in shorthand target positions.MachineConfigwraps it inDoNotInfer. This infrastructure supports the validation types but doesn't constrain anything on its own —ValidateConfigTargetsdoes the actual enforcement.Test coverage (
typesafe-states.test.ts)74 tests across
createMachineandsetup().createMachine. Every "should allow" has a matching "should reject" (@ts-expect-error):on: bare string, object-form{ target }, array of objectsalways: bare string, object-form, array of objectsafter: bare string, object-formonDone(state node): bare string, object-forminvoke.onDone/invoke.onError: bare string, object-form.child,#id,sibling.child, escaped dots ('foo\\.bar')initialunconstrained, spread variables pass through