Share and mutate object between different TypeScript classes

Viewed 1200

I have the following TypeScript code:

class ClassA {
    options: ClassOption;
    B: ClassB;

    constructor() {
        this.B = new ClassB(this.options);
        this.changeOptions();
    }

    changeOptions(): void {
        const newOptions: ClassOption = new ClassOption("something");
        this.options = newOptions;
    } 
}

class ClassB {
    options: ClassOption;

    constructor(opts: ClassOptions) {
        this.options = opts;
    }

    someFunction(): ClassOption {
        return this.options;
    }
}

The problem is that when I instantiate ClassA:

const a = new ClassA();

a.B.someFunction(); returns undefined instead of the new options that are set from ClassA's changeOptions method.

1 Answers

When in ClassA's constructor yo do:

this.B = new ClassB(this.options);

this.options is still undefined, so basically when in ClassB's constructor your do:

this.options = opt;

You are just setting this.options to undefined instead of assigning it a reference to ClassA's options, which doesn't exist as it hasn't been initialised.

Even if you initialise options in ClassA with an empty object, if you assign (this.options = something) a new value to it, ClassB won't be referencing the new value.

What you want to do instead is:

  1. Initialize ClassA's this.options with an empty object:

    options: ClassOption = {};
    
  2. Pass that to ClassB's constructor. No changes needed here.

  3. When calling ChangeOptions, mutate that same object instead of replacing it with a new one. You can use Object.assign to merge both objects:

    changeOptions(): void {
        const newOptions: ClassOption = new ClassOption("something");
        Object.assign(this.options, newOptions);
        // Note that after this, `this.options`' reference is preserved.
    } 
    

Here you can see it working in plain JavaScript:

class ClassA {
   constructor() {
      // 1. Initialise with an empty object:
      this.options = {};
      
      // 2. Pass that reference to ClassB instead of undefined:
      this.B = new ClassB(this.options);
      
      this.changeOptions();
   }
   
   changeOptions() {
      // 3. Mutate this.options without changing its reference:
      Object.assign(this.options, {
        opt1: 1,  
        opt2: 2, 
      });
      
      // 3. You can also do it like this:
      this.options.opt3 = 3;
   } 
}

class ClassB {
   constructor(options) {
      this.options = options;
   }
   
   getOptions() {
      return this.options;
   }
}
 
const a = new ClassA();

a.changeOptions();

console.log(a.B.getOptions());

Related