Circular Dependencies in TypeScript with State Pattern

33 views Asked by At

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.

0

There are 0 answers