The change in behavior you are experiencing is likely due to the useDefineForClassFields
setting being enabled now, whereas it was disabled before. According to the provided link:
Use Define For Class Fields - useDefineForClassFields
This flag is used when transitioning to the new standard version of class fields. TypeScript implemented class fields long before they were officially approved by TC39. The latest version of the upcoming specification has a different runtime behavior compared to TypeScript’s implementation but uses the same syntax.
This flag aligns with the upcoming ECMA runtime behavior.
You can find more information about this transition in the 3.7 release notes.
Essentially, after the constructor for A
finishes running, the (implicit) constructor of B
redefines the property, replacing the one defined by A
and losing the value created by A
in the process. This behavior mirrors JavaScript's behavior as described above.
To resolve this issue, you can disable the setting to achieve the desired output from your code; playground link (note: other type errors have not been fixed). However, it is recommended to update your code instead. From a design perspective, A
should not be initializing properties that it does not define. It is also not safe to assign all properties from an object to the instance being initialized.
One solution is to write constructors that explicitly copy the intended data. This approach ensures that instances do not inherit properties from source
that are not meant for them, as shown in the following JavaScript example (TypeScript version here [again, other type errors remain]):
class A { // A: Model
constructor(source){
Object.keys(source)
.forEach(key => {
if(!this[key]){
this[key] = source[key];
}
});
}
}
class B extends A{ // B: User
first_name;
}
let v = new B({first_name: "nof", shouldNotBeHere: "Hi there!"});
console.log(v);
// B { first_name: "nof", shouldNotBeHere: "Hi there!" }
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you prefer to have A
perform the blind copy, you can eliminate the compiler error (though not the problem itself) by disabling the flag.