As do the reducers. For example the following is a valid type signature.
function onToOff(initialState: "on", transition: "toggle"): "off"
In each of the if clauses those are what the types are inferred as, exactly equivalent in type safety to the classes (and more flexible because you can dispatch on action).
I chose string for simplicity (string literals happen to be distinct types on their own, I could easily use anything else other than strings, e.g. interfaces). Heck it could just be integers and be even simpler.
whose type signature has start and end state
> first-class entities
a string