Skip to content

Instantly share code, notes, and snippets.

@jtmthf
Created May 8, 2022 16:50
Show Gist options
  • Save jtmthf/133d951c6bc88539d3c1d4e9bc383fac to your computer and use it in GitHub Desktop.
Save jtmthf/133d951c6bc88539d3c1d4e9bc383fac to your computer and use it in GitHub Desktop.
interface Machine<State extends string, Event extends string> {
initialState: State;
transition(currentState: State, event: Event): State;
}
interface MachineDefinition<State extends string, Event extends string> {
initialState: State;
states: Record<State, {
entry?(): void;
exit?(): void;
on?: Record<Event, {
target?: State;
action?(): void;
}>;
}>;
}
function createMachine<State extends string, Event extends string>(definition: MachineDefinition<State, Event>): Machine<State, Event> {
return {
initialState: definition.initialState,
transition(currentState, event) {
const currentStateDefinition = definition.states[currentState];
const destinationTransition = currentStateDefinition?.on?.[event];
if (!destinationTransition) {
return currentState;
}
const destinationState = destinationTransition.target ?? currentState;
const destinationStateDefinition = definition.states[destinationState];
destinationTransition.action?.();
currentStateDefinition.exit?.();
destinationStateDefinition.entry?.();
return destinationState;
}
}
}
const machine = createMachine({
initialState: 'green',
states: {
green: {
entry() {
console.log('green: entry');
},
on: {
TIME_ELAPSED: {
target: 'yellow'
}
}
},
yellow: {
entry() {
console.log('yellow: entry');
},
on: {
TIME_ELAPSED: {
target: 'red'
}
}
},
red: {
entry() {
console.log('red: entry');
},
on: {
TIME_ELAPSED: {
target: 'green'
}
}
}
}
});
let state = machine.initialState;
console.log('current state:', state);
state = machine.transition(state, 'TIME_ELAPSED');
console.log('current state:', state);
state = machine.transition(state, 'TIME_ELAPSED');
console.log('current state:', state);
state = machine.transition(state, 'TIME_ELAPSED');
console.log('current state:', state);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment