A Feature, Not a Bug
Just to clarify, what you're experiencing is not a bug within TypeScript, Babel, or your JS runtime.
Understanding the Why
You may be wondering, "Why isn't this done correctly?" Let's delve into the specifics, focusing on TypeScript emit for different ECMAScript versions.
Downlevel Emit: ES3/ES5
When we inspect the emitted code for ES3 or ES5, it becomes apparent that the base class initialization precedes the constructor body in a logical sequence. This ensures that the fields are initialized before the constructor's execution, which is the desired behavior.
But what about the derived class?
No, the Order Matters
While some argue that the derived class initialization should occur first for various reasons, this approach is flawed. It disrupts the expected behavior and may lead to unintended consequences, especially in code like invoking base class methods relying on base class initializations.
Time Machine Required
Others propose a hypothetical solution involving informing the base class about derived class initializers. However, in a scenario where `Base` is in a separate file, this method isn't feasible for tools like TypeScript or Babel to implement.
Downlevel Emit: ES6
Classes are native to ES6, not TypeScript, and are transformed to ES6-compliant code. The sequence of super invocation and field initialization in derived classes follows a strict order due to language restrictions.
ES7+: Future Possibilities
The JavaScript committee is exploring options for field initializers in upcoming language versions, aiming to address these initialization challenges.
Object-Oriented Programming Principle Reminder
In OOP, a common guideline prohibits invoking virtual methods from constructors, extending to property initialization. This principle holds true across various languages, including JavaScript.
Potential Solutions
One recommended approach involves transforming field initialization into constructor parameters to ensure a predictable sequence of execution. Alternatively, an `init` pattern can be employed cautiously to avoid observing virtual behaviors during initialization.