javascripttypescriptthissolid-principles

Private props return unmodified or losing values within the class inside scope of child class method


So, I have two classes service-class & entity-class with private constructor & static async method, for creating new instance of class. My service-class create & call new entity-class instance and modified it with its properties.

Example | This is NOT NEST.JS code:

class Service {
   run() {
     const entity = Entity.createNewEntity(args);

     await entity.methodMother();

     const getMyProps1Back = entity.props1();

     // is [ ] empty array, not modified after methodChild
     console.log(getMyProps1Back);

   }
}

Each method of my entity is covered with bind decorator from npm: bind-decorator module

class Entity {
  this.props1! Array<Record<Type>>;
  this.props2 = new Map([]);


  private constructor(someArgs: any) {
     // some stuff
     this.props1 = [];  
  }

  get getProps1() {
    return this.props1;
  }

  static async createNewEntity() {
     const entity = new Entity();
     // blah-blah work here
     return entity;
  }

  @bind
  public async methodMother() {
    this.props1.push({ some: stuff });

    // 

    this.methodChild();
    // method logic
  }

  @bind
  private methodChild() {
     // adding more elements, or overwriting the array
     this.props1 = [test1, test2, test3];
  }
}

So my questions here are about explaining why context is lost during calling of methodChild within the methodMother and how is my getter return an unmodified array of props1?

## How does it work, and what should I do to avoid it?

Passing an array like argument and returning it back, like this? Or something else, like makign them anonymous?

  @bind
  private methodChild(props1 : Array<OfProps1>) {
     // adding more elements, or overwriting the array
     props1 = [test1, test2, test3];

     return arg;
  }

Solution

  • The code you've sent seems to work fine without the @bind decorator (After some clean-up):

    type KeyType = any
    type ValueType = any
    
    class Entity {
      props1!: Record<KeyType, ValueType>[];
      props2 = new Map([]);
    
    
      private constructor() {
        // some stuff
        this.props1 = [];
      }
    
      getProps1() { // <-- NOTE: Removed the `get` from here
        return this.props1;
      }
    
      static async createNewEntity() {
        const entity = new Entity();
        // blah-blah work here
        return entity;
      }
    
      public async methodMother() {
        this.props1.push({ some: 'stuff' });
    
        this.methodChild();
      }
    
      private methodChild() {
        this.props1 = [
          ...this.props1,// existing values
    
          { some: 'other stuff' },
          { evenMore: 'other stuff' },
          { andMore: 'other stuff' }
        ]
      }
    }
    

    And when you run it:

    class Service {
      async run() {
        const entity = await Entity.createNewEntity();
    
        await entity.methodMother();
    
        const getMyProps1Back = entity.getProps1();
    
        console.log(getMyProps1Back);
      }
    }
    

    You get a nice Output:

    [
      {
        some: "stuff",
      },
      {
        some: "other stuff",
      },
      {
        evenMore: "other stuff",
      },
      {
        andMore: "other stuff",
      }
    ]
    

    This is based on the code you have given.