FsmConfig
Defined in: types.ts:615
Configuration object for creating an FSM.
Examples
Section titled “Examples”Type Parameters
Section titled “Type Parameters”TCtx
The context type (Fsm) or client type (BehavioralFsm).
For Fsm, this is inferred from the context property. For BehavioralFsm,
it’s the client object type provided explicitly or as a generic parameter.
TStates
Section titled “TStates”TStates extends Record<string, Record<string, unknown>> = Record<string, Record<string, unknown>>
The literal states object type. Captured directly from
the naked states: TStates & ... intersection member below (ideally with
const on the factory’s generic to preserve string literal types) —
deliberately NOT derived from ValidateStates, so an empty or
function-only state can’t disable inference (see ValidateStates’
module comment for the full mechanism). Defaults to a loose record for
unconstrained usage.
TStateNames
Section titled “TStateNames”TStateNames extends string = keyof TStates & string
The state-name union, defaulted from TStates but
captured as its OWN parameter (see ValidateStates) so it’s available,
fully resolved, while handler bodies are still being type-checked.
TBubbles
Section titled “TBubbles”TBubbles extends string = never
The union of inputs this FSM declares via bubbles.
Defaults to never — most FSMs bubble nothing.
Properties
Section titled “Properties”bubbles?
Section titled “bubbles?”
optionalbubbles: readonlyTBubbles[]
Defined in: types.ts:666
Inputs this FSM fires at itself without handling them — expecting
whatever mounts it via _child to catch them through machina’s
nohandler-bubbling mechanism (see the “Input delegation” section of the
hierarchical states guide). Declaring a bubble does two things:
- Joins this FSM’s own typed input union, so a self-directed
fsm.handle("phaseComplete")(e.g. from inside_onEnter) type-checks without a cast. - Becomes part of this FSM’s mounting contract: any config that
mounts it via
_childmust handle every declared bubble in some state, re-declare it in its OWNbubbles(passing the obligation up another level), or carry a"*"catch-all — enforced at compile time byChildCoverage, which is intersected ontostatesbelow.
A bubble name is NOT a state name — it can’t be used as a string
shorthand transition target. Omit bubbles entirely (the default) for
an FSM that never expects a container to catch anything from it — such
an FSM can be mounted via _child anywhere with no obligations.
context?
Section titled “context?”
optionalcontext:TCtx
Defined in: types.ts:644
Initial context data. The type is inferred from this value and flows
into every handler’s ctx parameter.
For BehavioralFsm, this property is optional and serves only as a type constraint — the client object IS the context.
id:
string
Defined in: types.ts:625
Unique identifier for this FSM
initialState
Section titled “initialState”initialState:
NoInfer<TStateNames>
Defined in: types.ts:635
The state to start in. Must be a key of states.
Wrapped in NoInfer to prevent TypeScript from using this value as an
inference site for TStateNames. Without it, initialState: "green"
could narrow the state-name union to only have a “green” key. We want
inference to come exclusively from the states property.
states
Section titled “states”states:
TStates&ValidateStates<TCtx,TStates,TStateNames> &ChildCoverage<TStates,TStateNames,TBubbles>
Defined in: types.ts:677
State definitions. Keys become the state name union.
The intersection with the bare TStates is what makes literal-type
capture work for empty and function-only states (see ValidateStates’
module comment) — ValidateStates and ChildCoverage layer validation
and the bubble-coverage contract on top without becoming the inference
source themselves.