Reputation: 2969
I've been tearing what little of my hair out with Typescript (2.1) and classes, in particular a class that extends another class.
if I declare a function as
foo = () => {}
then I can safely use this
in the function
but I can't use super.foo()
, as I get the error
TypeError: (intermediate value).foo is not a function
if I declare the function as
foo() { }
then I can use super.foo()
but I can't be sure that this
is pointing to the same "this" all the time, depending on how the function is being called
how do I get round this problem ? I've seen some suggestions that I have to double-declare all the functions and bind
one to the other, but that seems ridiculous .. Doesn't typescript have some "magic" syntax sugar that coats all of this ugliness ?
thanks ;)
Upvotes: 2
Views: 107
Reputation: 220954
Class methods can either be on the instance or the prototype. You can't have your cake and eat it too, unfortunately.
When a method is on the instance, you get one closure per method per class instance, and each instance's closure has its own copy of _this
that makes it so the function can be arbitrarily invoked. But because the methods are bound to the instance, an instatation of the derived class does not create any extant method with the base class's method code.
When a method is on the prototype, you get one closure per method, and those methods are unbound and therefore must be called with the correct method syntax. Here you can invoke base class implementations because there's a known location to get the base class method from (BaseClass.prototype.methodName
).
A good solution is to write a protected static
base class method which handles the logic that foo
would have invoked, and let your instance methods defer to the static method. This is roughly the best of both worlds at the cost of one level of indirection.
Example:
class Base {
protected static foo(instance: Base) {
instance.counter++;
}
counter = 0;
foo = () => Base.foo(this);
}
class Derived extends Base {
foo = () => {
Base.foo(this);
this.counter *= 2;
}
}
Upvotes: 1