Description
The TypeScript specification currently reads:
The first statement in the body of a constructor must be a super call if both of the following are true:
- The containing class is a derived class.
- The constructor declares parameter properties or the containing class declares instance member variables with initializers.
It is reasonable in TypeScript to not permit this
to be referenced in a constructor before calling super
when there are initialized properties or constructor parameter properties because this
is not fully initialized until after super
is called. But broader restrictions on calling other code before super
that is not directly using this
don't seem that helpful and can be worked around anyway. So why keep them?
A common use case for having code before a call to super
is to transform constructor parameters in the subclass constructor before passing them to the superclass constructor. If such transformations are complex, a programmer might want to do the transformation step-by-step on multiple lines for increased readability and easier debugging.
An example of bypassing the compiler's restriction of no code before super
is just making function calls wrapping arguments to a super
call such as super(logThisName(name))
where the called function refers to this
.
As show by an example in the Handbook discussion linked below on improving the explanation for TypeScript constructor restrictions, ES6 permits other code in a constructor before a super
call (although accessing this
in called code would generate a runtime error before super was called). TypeScript is being more strict than what ES6 permits, and sometimes that is a good thing. But, is there any real value in this case by differing from what ES6 allows overall -- compared to just getting in the way? Why not always always allow code before a super
call when it does not use this
? Does the benefit of not allowing code before a super
sometimes really benefit anyone compared to the confusion caused by requiring programmers to use awkward workarounds and to learn a more complex rule for writing constructors than "Don't use this
before calling super
"?
This idea was originally brought up in issue #945 (closed in October 2014). I am creating a new issue for that as discussed with @mhegazy here: microsoft/TypeScript-Handbook#214. There is a code example in that Handbook issue which can be used for testing the current behavior for TypeScript, Babel, and ES6.
Activity
electricessence commentedon Apr 25, 2016
Yeah, this an interesting issue because I personally have had to write special cases where you have to pass closures to the super to ensure they get executed before other blocks of code.
There needs to be a way to allow for this.
On the other side of the coin, this is also an issue in C# as well because calling :base() you need to follow a similar pattern and have an onConstruct override or something like that.
Or... all your properties need to be lazy.. :/
iby commentedon May 3, 2016
I also have many cases where I check / initialise local variables before calling super. It's great that TypeScript uses the best from other well-typed languages, but the way it is right now is simply out of line with common sense. Like per @jbaron example:
That limitation doesn't bring in any value. There was an argument on complexity of the checks – doing check for
this
use beforesuper
shouldn't be hard, this is also the same logic used in Swift, which inherits the best from C languages.DanielRosenwasser commentedon Jul 19, 2016
It pretty much looks like this is fixed for 2.0 beta. Can you give it a try @pdfernhout?
martinsik commentedon Oct 26, 2016
@DanielRosenwasser It's probably all right now. The error message explains what went wrong precisely I think.
This is fine:
This is not:
captainjono commentedon Mar 30, 2017
Could someone tell me why this code is not permitted ?
`export class MatterAccessRevokedForUser extends MatterUserDomainEvent {
}`
56 remaining items