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:

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.

Leave a Reply