Type safe state machines in TypeScript

State machines are everywhere but I don’t think they get enough air time. To remedy the situation I’m going to present an implementation in TypeScript and use it to model a very simple elevator.

I could point you to the definition of what a state machine is on wikipedia but the name gives it away. State machines consist of states and a description of how to go from one state to the next. So let’s start spelling out the pieces.

First thing we need is a description of the states. I’m going to use basic types like strings, numbers, and symbols because it greatly simplifies the rest of the implementation and we don’t lose any generality

Next we need a description of the transition function/map

That definition looks a bit elaborate but in plain english it says for every state we have a function that takes an event (E[I]), the current state (I), some extra state (S), and gives us back the next state. The events are indexed by the possible states the machine can be in because not every event is valid in every state. There is no way to actually enforce this constraint at compile time so our transition functions must deal with all event types which is what E[I] is about.

Now we can construct the machine. We’ll use a class to model the machine with the above ingredients

The above machine doesn’t do much because we are not leveraging the transition functions so let’s remedy that

That’s it. We just implemented an abstract state machine. Abstract state machines aren’t that useful so let’s implement a concrete one that models an elevator in a 3 story building.

The elevator will start on the 1st floor and then go all the way to the 3rd floor. After reaching the 3rd floor it will go all the way down to the 1st floor and then repeat this cycle. Like I said, it’s very simple.

First thing we need is the description of the states. The most relevant part of the state is the floor the elevator is on so that’s what we’ll use for the state description

This elevator doesn’t take any inputs so the event mapping for each state is also very simple

We need one more bit of information. The elevator needs to know which direction its going

The transitions functions are a runtime concern so to fill those in we’re going to instantiate our abstract machine and fill them in

Let’s also step through the transitions a few times to verify that it’s working as we expect

Looks correct to me. Making the elevator less simple is left as an exercise for the reader. See if you can model people requesting to be taken to a specific floor as a starting point.

All the code along with the above example lives at GitHub: davidk01/state-machine.