Home > Net >  How to use non-static methods as callback functions and reference `this`?
How to use non-static methods as callback functions and reference `this`?

Time:10-12

Basically, I have the following TypeScript code:

export class ClassA {

  method1() {
    this.method2(new ClassB().method3);
  }

  method2(functionReference: () => void) {
    functionReference();
  }

}

export class ClassB {

  method3() {
    this.method4();
  }

  method4() {
    console.log("method4 invoked");
  }

}

Being more familiar with other OO programming languages (Java, C#, C ), I would expect that running new A().method1(); would eventually cause method4 in ClassB to be invoked. Instead I run into the problem, that this is undefined when method3 is eventually run and the execution fails:

TypeError: Cannot read properties of undefined (reading 'method4')

I am aware of all the trickery needed to get this to work in JavaScript, but I had hoped for the behaviour to be more intuitive in TypeScript. As long as method3 is a non-static method, I would expect to be able to reference this in the method, no matter from where the method is invoked.

Is there a not too cumbersome pattern available in TypeScript allowing me to use non-static methods as callback functions like I am trying to do here, or is it only possible to use static methods? The latter does not really sound correct, because if it had been so, I would expect the compiler to fail on this.method2(new ClassB().method3) where I try to pass a non-static method as a function reference.

CodePudding user response:

In javascript the class methods are not bind to its scope when you call them through a reference.

Your code will work correctly if you bind the function to the instance, or if you wrap the call in a function.

Some examples of how you could rewrite the method1 in class ClassA to make things work.

Binding the context to the function:

  method1() {
    const instance = new ClassB();
    this.method2(instance.method3.bind(instance));
  }

Wrapping the call:

  method1() {
    this.method2(()=>new ClassB().method3());
  }

CodePudding user response:

You can define the method whose reference you want to pass as a class property

class ClassB {

  method3 = () => {
    this.method4();
  }

  method4() {
    console.log("method4 invoked");
  }

}

this way it will be defined as arrow function upon initialization and the this reference will be preserved

TS Playground

  • Related