Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: How to call method defined with arrow function in base class using super keyword in child class?

Given

class BaseClass{

  count:number=0;

  public someMethod=():void =>{
      this.count++;
  }
}

class ChildClass extends BaseClass{
  public someMethod=():void=>{
     super.someMethod();
     //Do more work here.
  }
}

I receive the error message:

Only public methods of the base class are accessible via the 'super' keyword.

@Basarat provides some information here but this seems like a real hack to the language. typescript arrow operator to define a function on prototype

How might this be done while preserving contextual use of 'this'?

Am I using arrow functions properly or should they really only be used as a method of declaring something like a callback?

like image 555
Richard Collette Avatar asked Apr 22 '14 12:04

Richard Collette


People also ask

Can I use arrow functions in methods?

Arrow functions don't have their own bindings to this , arguments or super , and should not be used as methods. Arrow functions don't have access to the new. target keyword.

What means => in TypeScript?

In a type position, => defines a function type where the arguments are to the left of the => and the return type is on the right. So callback: (result: string) => any means " callback is a parameter whose type is a function.

Can I use arrow functions in TypeScript?

ES6 version of TypeScript provides an arrow function which is the shorthand syntax for defining the anonymous function, i.e., for function expressions. It omits the function keyword. We can call it fat arrow (because -> is a thin arrow and => is a "fat" arrow).

How do you use arrow method in object method?

Arrow functions cannot be used to write object methods because, as you have found, since arrow functions close over the this of the lexically enclosing context, the this within the arrow is the one that was current where you defined the object. Which is to say: // Whatever `this` is here...


2 Answers

For the sake of argument, assume you

  • Are using the fat-arrow syntax because the methods are being triggered by UI events or callbacks (in my case knockout click events)
  • Need inheritance to eliminate redundancy in UI (or callback) respondent code.

A minimally hackish (if not elegant) answer is to split your function into two calls that address the two issues:

Class A {
    public handleScope = () => {
        return this.handleInheritance();
    }

    public handleInheritance() {
        // do work
    }
}

Class B extends A {
    public handleInheritance() {
         super.handleInheritance() // super works here
         // additional work
    }
}

I'm the first to admit that doubling functions is "ugly", but IMHO a lot less ugly than the other options I've seen. To help standardize naming, I'm naming the one-line "scoping" function the name of the base function (e.g. myFunction) plus "Scoper" (i.e. myFunctionScoper). This is also IDE-friendly because you'll often get the Scoper method as a hinted option when you start to type the name for the inheritable method.

like image 139
claytond Avatar answered Oct 27 '22 17:10

claytond


arrow functions properly or should they really only be used as a method of declaring something like a callback?

They should really only be used for callbacks. If you want a class hierarchy then use the prototype. prototype also saves you memory.

Forced fix: there is only one this and it is the current instance. If you overwrite this.foo in the child class the base instances this.foo is lost. Preserve the base version in the constructor

class BaseClass{

  count:number=0;

  public someMethod=():void =>{
      this.count++;
  }
}

class ChildClass extends BaseClass{

  constructor(){      
      super();
      var baseSomeMethod = this.someMethod;
      this.someMethod = ()=>{
          // implement here 
      }
  }

}
like image 27
basarat Avatar answered Oct 27 '22 18:10

basarat