I am implementing the State design pattern in TypeScript and have run into circular dependency issues between Context, State, and state classes (StateA and StateB).
// context.ts
import { State } from "./state";
export class Context {
private state: State;
constructor(state: State) {
this.transitionTo(state);
}
public transitionTo(state: State): void {
console.log(`Context: Transition to ${(<any>state).constructor.name}.`);
this.state = state;
this.state.setContext(this);
}
public request1(): void {
this.state.handle1();
}
public request2(): void {
this.state.handle2();
}
}
// state.ts`
import { Context } from "./context";
export abstract class State {
protected context: Context;
public setContext(context: Context) {
this.context = context;
}
public abstract handle1(): void;
public abstract handle2(): void;
}
// stateA.ts
import { State } from "./state";
import { StateB } from "./stateB";
export class StateA extends State {
public handle1(): void {
console.log('StateA handles request1.');
console.log('StateA wants to change the state of the context.');
this.context.transitionTo(new StateB());
}
public handle2(): void {
console.log('StateA handles request2.');
}
}
// stateB.ts
import { State } from "./state";
import { StateA } from "./stateA";
export class StateB extends State {
public handle1(): void {
console.log('StateB handles request1.');
}
public handle2(): void {
console.log('StateB handles request2.');
console.log('StateB wants to change the state of the context.');
this.context.transitionTo(new StateA());
}
}
The StateA and StateB classes switch back and forth between each other, leading to a circular dependency. Also, the Context class imports State, and State imports Context.
I expect to have 5-10 states and ~10 requests which the states have different implementations for.
I have tried restructuring the code, but have not been able to find a way that would avoid circular dependencies. I also tried import type within the stateA and stateB classes, but that doesn't work because they create a new instance of that type.