Type safe non-deterministic state machines
npm install @davidk01/state-machinetest/test.ts for a use case. It is inlined below with an explanation of what is going on.
typescript
import * as machine from '../src/index';
// Building with 3 floors
type Floor = 0 | 1 | 2;
// There are no allowed event types because the elevator operates without inputs
type AllowedEvents = { 0: void; 1: void; 2: void };
`
We also need some extra state to figure out what part of the cycle we are on (are we going up or down?)
`typescript
// Keep track of where the elevator was before
type ElevatorState = { previousFloor: Floor };
`
Now we can instantiate the machine along with the state transitions
`typescript
const elevator = new machine.Machine(
{ previousFloor: 0 },
0, // We start at ground level
{
0: (e, f, s) => { // We can only go up when we are at ground level
s.previousFloor = 0;
return 1;
},
1: (e, f, s) => { // This is where we need to figure out whether to go up or down
const previousFloor = s.previousFloor;
s.previousFloor = 1;
if (previousFloor === 2) { // We were at the top so we must go down
return 0;
}
if (previousFloor === 0) { // We were at ground level so we need to go up
return 2;
}
},
2: (e, f, s) => { // We can only go down when we are on the last floor
s.previousFloor = 2;
return 1;
}
}
);
`
Run the elevator by stepping through the transitions
`typescript
// Let's step a few times and see what is going on
console.log(starting);
for (let i = 0; i < 12; i++) {
const [previousFloor, nextFloor] = elevator.step(void(0));
console.log(Elevator went up/down: ${previousFloor} => ${nextFloor});
if (nextFloor === 0) {
console.log(---Cycle complete---);
}
}
console.log(done);
`
`
starting
Elevator went up/down: 0 => 1
Elevator went up/down: 1 => 2
Elevator went up/down: 2 => 1
Elevator went up/down: 1 => 0
---Cycle complete---
Elevator went up/down: 0 => 1
Elevator went up/down: 1 => 2
Elevator went up/down: 2 => 1
Elevator went up/down: 1 => 0
---Cycle complete---
Elevator went up/down: 0 => 1
Elevator went up/down: 1 => 2
Elevator went up/down: 2 => 1
Elevator went up/down: 1 => 0
---Cycle complete---
done
``