Skip to content

Instantly share code, notes, and snippets.

@leonrinkel
Created June 13, 2021 13:30
Show Gist options
  • Save leonrinkel/5078b845b60dd6be5fa02a1fe8f6c28a to your computer and use it in GitHub Desktop.
Save leonrinkel/5078b845b60dd6be5fa02a1fe8f6c28a to your computer and use it in GitHub Desktop.
Typescript State Machine
interface TrafficLightOperations {
onButtonPressed(): void;
onWaitedToTurnGreen(): void;
waitToTurnRed(): void;
onWaitedToTurnRed(): void;
}
interface TrafficLightContext {
activeLight?: "red" | "green";
}
abstract class TrafficLightState implements TrafficLightOperations {
protected instance: TrafficLight;
constructor(instance: TrafficLight) {
this.instance = instance;
}
public abstract get name(): string;
public abstract handle(): void;
public onButtonPressed(): TrafficLightState {
throw new Error("Method not implemented.");
}
public onWaitedToTurnGreen(): TrafficLightState {
throw new Error("Method not implemented.");
}
public waitToTurnRed(): TrafficLightState {
throw new Error("Method not implemented.");
}
public onWaitedToTurnRed(): TrafficLightState {
throw new Error("Method not implemented.");
}
}
class TrafficLightRedState extends TrafficLightState {
public get name(): string { return "Red"; }
public handle(): void {
this.instance.activeLight = "red";
}
public onButtonPressed(): TrafficLightWaitingToTurnGreenState {
return new TrafficLightWaitingToTurnGreenState(this.instance);
}
}
class TrafficLightWaitingToTurnGreenState extends TrafficLightState {
public get name(): string { return "WaitingToTurnGreen"; }
public handle(): void {
setTimeout(() => this.instance.onWaitedToTurnGreen(), 1000);
}
public onWaitedToTurnGreen(): TrafficLightGreenState {
return new TrafficLightGreenState(this.instance);
}
}
class TrafficLightGreenState extends TrafficLightState {
public get name(): string { return "Green"; }
public handle(): void {
this.instance.activeLight = "green";
setTimeout(() => this.instance.waitToTurnRed());
}
public waitToTurnRed(): TrafficLightWaitingToTurnRedState {
return new TrafficLightWaitingToTurnRedState(this.instance);
}
}
class TrafficLightWaitingToTurnRedState extends TrafficLightState {
public get name(): string { return "WaitingToTurnRed"; }
public handle(): void {
setTimeout(() => this.instance.onWaitedToTurnRed(), 1000);
}
public onWaitedToTurnRed(): TrafficLightRedState {
return new TrafficLightRedState(this.instance);
}
}
class TrafficLight implements TrafficLightOperations {
private _context: TrafficLightContext;
private _state: TrafficLightState;
constructor() {
this._context = {};
this._state = new TrafficLightRedState(this);
}
set activeLight(activeLight: "red" | "green" | undefined) {
this._context.activeLight = activeLight;
console.log(`traffic light changed to ${activeLight}`);
}
get activeLight() {
return this._context.activeLight;
}
onButtonPressed(): void {
this._state = this._state.onButtonPressed();
console.log(`state transitioned to ${this._state.name}`);
this._state.handle();
}
onWaitedToTurnGreen(): void {
this._state = this._state.onWaitedToTurnGreen();
console.log(`state transitioned to ${this._state.name}`);
this._state.handle();
}
waitToTurnRed(): void {
this._state = this._state.waitToTurnRed();
console.log(`state transitioned to ${this._state.name}`);
this._state.handle();
}
onWaitedToTurnRed(): void {
this._state = this._state.onWaitedToTurnRed();
console.log(`state transitioned to ${this._state.name}`);
this._state.handle();
}
}
const trafficLight = new TrafficLight();
setTimeout(() => trafficLight.onButtonPressed(), 1000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment