discuss: constructors, super, virtual methods and initialization order

Topics: Language Specification
May 27, 2013 at 1:26 AM
Edited May 27, 2013 at 1:28 AM
The rules for super() and this in section 8.3.2 are somewhat obtuse, but the goal seems to be the prevention of accessing "this" from subclass before the subclass's constructor is complete. More specifically, before the class-body and constructor-arg initialized members are set.

Nevertheless, I ran into this construct which is compatible with the rules but still suffers from the issue the language is try to address:
class Base {
  constructor() { this.onInit(); }
  onInit() { }
}

class Derived extends Base() {
   public data:any = {};
   constructor() {
     super(); // calls this.onInit()
     // this.data set immediately after super();
   }
   onInit() {
     this.data.x = 'x'; // this.data not set yet. crash when doing new Derived()
   }
}
I'm not sure how this should be resolved, one way might involve splitting the member assignment step into separate method and call it for each class in the hierarchy before the body of the constructor is run. Or the language might have some clear way of forbidding this construct.

I see pros and cons to both answers.
Coordinator
May 28, 2013 at 9:03 PM
Calling virtual methods from the constructor is widely viewed as a bad thing to do. While it's not enforced as a language rule in TypeScript (because there's no concept of 'virtual'), this would be a good place for a static analysis tool to issue a warning (as FxCop does for C# or VB code; in C++, doing this results in 'undefined' behavior and is typically disallowed by the compiler).

There's no call or initialization order that would preserve sane semantics in the presence of virtual function calls from the constructor, so I think the only solution here is "Please don't do that" until someone writes a nice FxCop-like tool for TypeScript.
May 28, 2013 at 10:24 PM
Thanks for the response.

Clearly this is a case of
Patient: "doctor it hurts when I do this"
Doctor: "so don't do that"

I'm not entirely satisfied with this answer, but I can't really come up with anything better, either. grumble grumble