Skip to content

TypeScript immutable data/classes with mutual reference

Usually when I create a TypeScript application I follow an OOP + immutable data philosophy.

So let’s suppose I have two classes with mutual reference, class A and class B.

class A {
    public readonly item: B;

    public constructor (item: B) {
        this.item = item;
    }
}

class B {
    public readonly item: A;

    public constructor (item: A) {
        this.item = item;
    }
}

Now it’s impossible to create instance of class A, since class B is required in constructor to achieve immutability, and class B requires instance of class A.

It’s required to create first an instance of class A and B with item property set to undefined and then respectively assign the references after class instantiation. But this solution will break immutability since it will allow users to overwrite the item property.

Any proposed solution?

Answer

One way is use getter to achieve lazy evaluation,

class A {
  private readonly _item: () => B;
  public get item(): B {
    return this._item();
  }

  public constructor(_item: () => B) {
    this._item = _item;
  }
}

class B {
  public readonly _item: () => A;
  public get item(): A {
    return this._item();
  }
  public constructor(_item: () => A) {
    this._item = _item;
  }
}

const a: A = new A(() => b);
const b: B = new B(() => a);

console.log(a.item === b); // true