Reputation: 2307
after some fiddling, I ended up writing this in TypeScript:
class B extends A{
constructor() {
const c = new C(() => this.method());
super(c);
c.someMethod(this);
}
}
And it works ...
Let's set aside why I did this for a second (irrelevant to my question)
My questions are :
super
?!const c = new C(() => this.method());
closure this
when it is not yet defined ?
this
should not be available or I'd rather have done const c = new C(this.method);
but it did not compile, complaining that this is not, yet, available
.I am missing something there :/
Upvotes: 0
Views: 30
Reputation: 327964
Yeah, I think I see why this is bothering you. The relevant issue in GitHub is Microsoft/TypeScript#3311. Let's see if I can answer these questions:
- How in the world does it compile when I do things before the call to
super
?!
Apparently it's because you don't have member initializers. From the linked issue:
You can call
super
whenever you want if you don't have member initializers...If you look at how class member initializers are emitted, the reasoning for this becomes fairly clear. Member initializers are emitted after the super call (otherwise your derived-class initializers wouldn't properly overwrite base class initializations); by enforcing the super call to be the first thing the compiler can guarantee that there's exactly one (correct) place to emit those initializers.
You move the super call to any position by removing member initializers -- this makes explicit what you expect the initialization order of each class member to be.
I think the language designers think there are some legitimate things someone could do before the super
call (e.g., doing some computations to determine what to pass into the call to super
), but that a few things are problematic: member initializers (which emit to JS as references to this
), and explicit references to this
.
- at least this should not be available or I'd rather have done const
c = new C(this.method);
but it did not compile, complaining thatthis is not, yet, available
Right, you can't refer to the bare this.method
before the call to super
because this
is not guaranteed to exist at that time.
- How can the line
const c = new C(() => this.method());
closurethis
when it is not yet defined ?
My guess about the closure being accepted is that the reference to this
must not be considered to come lexically before the super
call. This might or might not be a bug or design limitation in the compiler. In your case, if the constructor of C
doesn't actually call the function, then there's probably not an issue... the closure can potentially defer the dereferencing of this.method
until after the subclass constructor is complete. But since the constructor of C
might call the function, the code could be unsafe.
If you feel strongly that this should give a compiler warning, you might want to raise an issue in GitHub and reference Microsoft/TypeScript#3311 (you can't comment on that issue because it's been locked).
Hope that helps. Good luck!
Upvotes: 2