createBehavioralFsm
Call Signature
Section titled “Call Signature”createBehavioralFsm<
TClient>(): <TStates,TStateNames,TBubbles>(config) =>BehavioralFsm<TClient, keyofTStates&string,TBubbles|Exclude<{ [S in string | number | symbol]: keyof TStates[S] & string }[keyofTStates],SpecialStateKeys> | { [S in string | number | symbol]: TStates[S] extends { _child: C } ? InputNamesOfInstance<C> : never }[keyofTStates],TBubbles>
Defined in: behavioral-fsm.ts:1185
Create a behavioral FSM (one definition, many clients) from a config object.
TClient can’t be inferred from the config — there’s no context property
at the FSM level for it to hook into, unlike createFsm’s TCtx. Supplying
it as a single explicit type argument (createBehavioralFsm<Connection>({...}))
doesn’t work either: TypeScript has no partial type-argument inference, so
providing one of two type parameters disables inference for the other,
widening TStates to Record<string, Record<string, unknown>> and
discarding all literal-type validation.
The fix is currying: call with zero arguments to fix TClient, then call
the returned function with the config to infer TStates from it, const
literal capture and all. This is the recommended way to type a client.
If you’d rather skip the type argument entirely, annotate ctx inline on
at least one handler (e.g. disconnect({ ctx }: { ctx: Connection }) {...})
and call with zero type arguments — TClient is then inferred from that
annotation. This only works when the annotation is visible directly on a
handler; it does NOT work through object spread (...guards), since
TypeScript won’t look inside a spread for the annotation.
Type Parameters
Section titled “Type Parameters”TClient
Section titled “TClient”TClient extends object
Returns
Section titled “Returns”<
TStates,TStateNames,TBubbles>(config):BehavioralFsm<TClient, keyofTStates&string,TBubbles|Exclude<{ [S in string | number | symbol]: keyof TStates[S] & string }[keyofTStates],SpecialStateKeys> | { [S in string | number | symbol]: TStates[S] extends { _child: C } ? InputNamesOfInstance<C> : never }[keyofTStates],TBubbles>
Type Parameters
Section titled “Type Parameters”TStates
Section titled “TStates”TStates extends Record<string, Record<string, unknown>>
TStateNames
Section titled “TStateNames”TStateNames extends string = keyof TStates & string
TBubbles
Section titled “TBubbles”TBubbles extends string = never
Parameters
Section titled “Parameters”config
Section titled “config”FsmConfig<TClient, TStates, TStateNames, TBubbles>
Returns
Section titled “Returns”BehavioralFsm<TClient, keyof TStates & string, TBubbles | Exclude<{ [S in string | number | symbol]: keyof TStates[S] & string }[keyof TStates], SpecialStateKeys> | { [S in string | number | symbol]: TStates[S] extends { _child: C } ? InputNamesOfInstance<C> : never }[keyof TStates], TBubbles>
Examples
Section titled “Examples”Call Signature
Section titled “Call Signature”createBehavioralFsm<
TClient,TStates,TStateNames,TBubbles>(config):BehavioralFsm<TClient, keyofTStates&string,TBubbles|Exclude<{ [S in string | number | symbol]: keyof TStates[S] & string }[keyofTStates],SpecialStateKeys> | { [S in string | number | symbol]: TStates[S] extends { _child: C } ? InputNamesOfInstance<C> : never }[keyofTStates],TBubbles>
Defined in: behavioral-fsm.ts:1207
Create a behavioral FSM (one definition, many clients) from a config object.
TClient can’t be inferred from the config — there’s no context property
at the FSM level for it to hook into, unlike createFsm’s TCtx. Supplying
it as a single explicit type argument (createBehavioralFsm<Connection>({...}))
doesn’t work either: TypeScript has no partial type-argument inference, so
providing one of two type parameters disables inference for the other,
widening TStates to Record<string, Record<string, unknown>> and
discarding all literal-type validation.
The fix is currying: call with zero arguments to fix TClient, then call
the returned function with the config to infer TStates from it, const
literal capture and all. This is the recommended way to type a client.
If you’d rather skip the type argument entirely, annotate ctx inline on
at least one handler (e.g. disconnect({ ctx }: { ctx: Connection }) {...})
and call with zero type arguments — TClient is then inferred from that
annotation. This only works when the annotation is visible directly on a
handler; it does NOT work through object spread (...guards), since
TypeScript won’t look inside a spread for the annotation.
Type Parameters
Section titled “Type Parameters”TClient
Section titled “TClient”TClient extends object
TStates
Section titled “TStates”TStates extends Record<string, Record<string, unknown>>
TStateNames
Section titled “TStateNames”TStateNames extends string = keyof TStates & string
TBubbles
Section titled “TBubbles”TBubbles extends string = never
Parameters
Section titled “Parameters”config
Section titled “config”FsmConfig<TClient, TStates, TStateNames, TBubbles>
Returns
Section titled “Returns”BehavioralFsm<TClient, keyof TStates & string, TBubbles | Exclude<{ [S in string | number | symbol]: keyof TStates[S] & string }[keyof TStates], SpecialStateKeys> | { [S in string | number | symbol]: TStates[S] extends { _child: C } ? InputNamesOfInstance<C> : never }[keyof TStates], TBubbles>