Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Need explanation of error message 'TypeError: Receiver must be an instance of class'

When I run this code:

'use strict';

class Base {
  constructor() {
    this._public();
  }
}

class Child extends Base {
  constructor() {
    super();
  }

  _public() {
    this.#privateMethod();
  }

  #privateMethod() {
    this.bar = 1234;
  }
}

const c = new Child();
console.log(c.bar);

I get the following error:

   this.#privateMethod();
         ^

TypeError: Receiver must be an instance of class Child

As I understand JavaScript, the receiver in the following code is exactly an instance of the class Child. It’s even shown in the dev tools inspector:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

dev-tools screenshot

So could someone please explain to me what’s going on? Is it a bug or what?


Actually FF shows a more accurate error message:

Uncaught TypeError: can't access private field or method: object is not the right class

>Solution :

This is one example of why it’s best not to call public instance methods from constructors. When your Base class constructor calls this._public(), Child‘s initialization is not (yet) complete. The earliest you can use Child members is after super() has returned, not before. It’s only after super() returns that Child‘s automatic initialization (such as setting up private fields and methods, and initializing public properties defined via class fields syntax) is complete. You can see this with public class fields as well:

class Base {
    constructor() {
        console.log("test" in this); // false
    }
}

class Child extends Base {
    test; // <== Public class field
    
    constructor() {
        super();
        console.log("test" in this); // true
    }
}

new Child();

You’re okay to call this._public() from Child‘s constructor just after super() returns (although, again, it’s best not to call public methods from constructors! better to call #privateMethod directly), because Child will be fully ready by then (other than any initialization you’re doing in its constructor, of course), but not before super() returns.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading