A strongly typed state machine
yarn add tasmania
tasmania
exports the following members:
import {
createReducer,
State,
Transitions
} from 'tasmania';
It's the single factory function for creating state reducers, it takes a single argument which defines the state transitions.
T
represents a Transitions definition andD
may be any type of data carried over.
createReducer<
{
A: 'B'
B: 'END'
END: null
},
{ ended: boolean }
>({
A: () => {
return { type: 'B', data: { ended: false } }
},
B: () => {
return { type: 'END', data: { ended: true } }
},
END: endState,
})
A structure reprenseting the machine state, with the signature { type: keyof T, data: D }
.
T
represents a Transitions definition andD
may be any type of data carried over.
A structure representing the machine transitions definition, with the signature { [K: keyof T]: (data: D) => { type: keyof T, data: D } | void }
.
T
represents a Transitions definition andD
may be any type of data carried over.
Here's a throughout usage example.
First we need to import the createReducer
function from this library.
import { createReducer } from 'tasmania';
Let's now create a simple but complete state machine that will track hypothetical matter state transitions.
import { createReducer } from 'tasmania';
enum State {
SOLID = 'SOLID',
LIQUID = 'LIQUID',
GAS = 'GAS',
ETHEREAL = 'ETHEREAL',
}
function run() {
const reduce = createReducer<
{
[State.SOLID]: Exclude<State, State.SOLID>;
[State.LIQUID]: Exclude<State, State.LIQUID>;
[State.GAS]: Exclude<State, State.GAS>;
[State.ETHEREAL]: null; // Halts here
},
State[]
>({
[State.SOLID]: (data) => {
if (Math.random() > 0.95) {
return {
type: State.ETHEREAL,
data: [...data, State.ETHEREAL],
};
}
if (Math.random() > 0.5) {
return {
type: State.LIQUID,
data: [...data, State.LIQUID],
};
}
return {
type: State.GAS,
data: [...data, State.GAS],
};
},
[State.LIQUID]: (data) => {
if (Math.random() > 0.95) {
return {
type: State.ETHEREAL,
data: [...data, State.ETHEREAL],
};
}
if (Math.random() > 0.5) {
return {
type: State.GAS,
data: [...data, State.GAS],
};
}
return {
type: State.SOLID,
data: [...data, State.SOLID],
};
},
[State.GAS]: (data) => {
if (Math.random() > 0.95) {
return {
type: State.ETHEREAL,
data: [...data, State.ETHEREAL],
};
}
if (Math.random() > 0.5) {
return {
type: State.LIQUID,
data: [...data, State.LIQUID],
};
}
return {
type: State.SOLID,
data: [...data, State.SOLID],
};
},
[State.ETHEREAL]: () => {
return;
},
});
console.log(
reduce({
type: Object.values(State)[
Math.floor(Math.random() * (Object.keys(State).length - 1))
],
data: [],
}),
);
}
run();