Type helpers
XState makes several type helpers available to you for composing types in TypeScript. You can use these helpers for creating custom functions or typing various integrations.
StateFrom
​
StateFrom
can be used to extract the State
from a machine.
import { createMachine, StateFrom } from 'xstate';
const machine = createMachine({
schema: {
context: {} as {
count: number;
},
},
});
const myFunction = (state: StateFrom<typeof machine>) => {
const context = state.context;
};
ContextFrom
​
ContextFrom
can be used to extract the context
from a machine.
import { createMachine, ContextFrom } from 'xstate';
const machine = createMachine({
schema: {
context: {} as {
count: number;
},
},
});
const myFunction = (context: ContextFrom<typeof machine>) => {
console.log(context);
};
EventFrom
​
EventFrom
can be used to extract the event
types from a machine
import { createMachine, EventFrom } from 'xstate';
const machine = createMachine({
schema: {
events: {} as
| {
type: 'FOO';
}
| {
type: 'BAR';
value: string;
},
},
});
const myFunction = (event: EventFrom<typeof machine>) => {
console.log(event);
};
You can also extract specific events by passing the type to the second generic slot.
import { createMachine, EventFrom } from 'xstate';
const machine = createMachine({
schema: {
events: {} as
| {
type: 'FOO';
}
| {
type: 'BAR';
value: string;
},
},
});
const myFunction = (event: EventFrom<typeof machine, 'BAR'>) => {
console.log(event);
};
InterpreterFrom
​
InterpreterFrom
gives you the type of the actor returned from interpret
or useInterpret
.
import { createMachine, InterpreterFrom } from 'xstate';
const machine = createMachine({
schema: {
context: {} as {
count: number;
},
},
});
const myFunction = (actor: InterpreterFrom<typeof machine>) => {
const context = actor.state.context;
};
ActorRefFrom
​
ActorRefFrom
is especially useful when spawning actors because it types the reference created by spawn
when assigning to context.
import { createMachine, ActorRefFrom, spawn, assign } from 'xstate';
const childMachine = createMachine({});
const machine = createMachine({
schema: {
context: {} as {
spawnedChild: ActorRefFrom<typeof childMachine>;
},
},
entry: [
assign((context, event) => {
return {
spawnedChild: spawn(childMachine),
};
}),
],
});
MachineOptionsFrom
​
You can use MachineOptionsFrom
in combination with typegen to get a strongly typed version of the machine’s options.
export interface Typegen0 {
'@@xstate/typegen': true;
eventsCausingActions: {
sayHello: 'xstate.init';
};
internalEvents: {
'xstate.init': { type: 'xstate.init' };
};
invokeSrcNameMap: {};
missingImplementations: {
actions: 'sayHello' | 'sayHelloAgain';
actors: never;
guards: never;
delays: never;
};
eventsCausingactors: {};
eventsCausingGuards: {};
eventsCausingDelays: {};
matchesStates: undefined;
tags: never;
}
import { createMachine, MachineOptionsFrom } from 'xstate';
const machine = createMachine({
schema: {
context: {} as {
count: number;
},
},
entry: ['sayHello', 'sayHelloAgain'],
tsTypes: {} as import('./myMachine.typegen').Typegen0,
});
const options: MachineOptionsFrom<typeof machine> = {
actions: {
sayHello: (context) => {},
},
};
You can also pass true
to the second element of the generic to ensure that all missing implementations are passed. In the example below, sayGoodbye
is missing, so must be passed when you pass true
to MachineOptionsFrom
.
export interface Typegen0 {
'@@xstate/typegen': true;
eventsCausingActions: {
sayHello: 'xstate.init';
};
internalEvents: {
'xstate.init': { type: 'xstate.init' };
};
invokeSrcNameMap: {};
missingImplementations: {
actions: 'sayGoodbye';
actors: never;
guards: never;
delays: never;
};
eventsCausingactors: {};
eventsCausingGuards: {};
eventsCausingDelays: {};
matchesStates: undefined;
tags: never;
}
import { createMachine, MachineOptionsFrom } from 'xstate';
const machine = createMachine(
{
entry: ['sayHello'],
exit: ['sayGoodbye'],
tsTypes: {} as import('./myMachine.typegen').Typegen0,
},
{
actions: {
sayHello: () => {
console.log('Hello');
},
},
},
);
const options: MachineOptionsFrom<typeof machine, true> = {
actions: {
/**
* This MUST be passed because of the `true` passed in above
*/
sayGoodbye: () => {},
},
};