-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Relax the rule that ‘super’ call must be the first statement #945
Comments
Totally 100% agree! I ran into some issues with this in my TypeScript code and I would have loved to have had this feature. This is the first language I've used where it forces you to call the Unless it's a code smell of which I was not aware. In which case, please provide information as to how it's a code smell or bad practice to do otherwise. |
C#, C++, and Java enforce this rule - it's not an uncommon one. Basically there's nothing valid you can do that must come before the base class super call. It's sometimes annoying in the case where you'd like to use the result of a function call more than once, but it's important to not try to use the base class before it's been initialized. |
Actually, it doesn't force you to have it first all the time. Works:blah:number;
constructor() {
var somethingbeforetheconstructor = 10;
this.blah = somethingbeforetheconstructor;
super();
} Doesn't Work:blah:number = 10;
constructor() {
var somethingbeforetheconstructor = 10;
var whatIsBlah = this.blah; // will be undefined;
super();
} This example it makes sense to fail because there are too many conditions to check where there might be problems since blah actually get's initialized after the constructor. Doesn't Work:constructor(public blah:number) {
var somethingbeforetheconstructor = 10;
super();
} This sample should be able to work and the compiler should go ahead and initialize the blah value before the constructor code begins. |
The exact rules from the spec explaining the above behavior (8.3.2):
As Ryan said, for the cases that are disallowed there are workarounds, because for the most part you can't do many safe things this way.
You mean like this? class Base {
blah = 4;
}
class Derived extends Base {
constructor(public blah: number) {
this.blah = blah;
super();
}
}
var d = new Derived(3);
console.log(d.blah); |
Agree that most problems come when using initialized properties. If you would indeed avoid them, more things are allowed (I guess I just a fan of intializing properties early on, since it saves some typing and for feels a bit more natural). But I would also have expected that a simple rule like no access to this before the super call would be easy to implement and understand, while provide still lots of posiibilities to do stuff before the super call. So the following would work (since there is no reference to this before the super call):
At the end there are ways around it, so no deal breaker. Just after using TypeScript extensively noticed that the current implemented rule is more often than not a (minor) annoyance. |
That case is the same as the parameter property one. Replace the definition of my |
Not sure I get that. How can a local scoped variable (var somethingbeforetheconstructor = 10) ever be overwritten by something in the base class constructor? Am I missing something? My typical use case would be something like this (just to demonstrate it with an example that in my endeavors with TypeScript regular occurs):
Ofcourse my current workaround would be to invoke the super call as follows to avoid the compiler complaints:
|
We'd still have to do fairly extensive analysis to determine whether or not you were indirectly using |
I suggest this issue be reopened based on discussion here: microsoft/TypeScript-Handbook#214 While it is reasonable in TypeScript to not permit |
Most cloud services offer database connection string as URI, not username and password. This branch adds ability to initialize Sequelize using URI connection string, eg. "postgres://user:pass@host/db", by either calling Sequelize.init(URI, config) or adding "uri" property into config object in Sequelize.init(config) call. Due to Typescript's limitation that doesn't allow passing spreaded arguments into super() nor conditional super() call, this change will break backward compatability by removing the constructor and replaced by static init() method. (Refer to microsoft/TypeScript#4130 and microsoft/TypeScript#945) new Sequelize(config) won't work anymore, use Sequelize.init() instead.
Right now the compiler always checks if a super call is made, it is indeed the first statement in the constructor. This is even true if the statements before the super call don’t access anything of the object just being constructed.
It would be nice to not allow access to object variables and methods but allow for other kind of statements. For example the following gives an warning:
while the following is ok:
Of course the sequence of commands in the above two example is the same (and one might argue that the second example is the less maintainable/debuggable code). So would be great if the first example wouldn't throw a compiler warning.
I guess the tricky part is to determine which statements are ok to be used before the super call. But I would assume if the statements don’t include this or super keywords, they should be ok.
The text was updated successfully, but these errors were encountered: