Skip to content

Always allow code before super call when it does not use "this" #8277

Closed
@pdfernhout

Description

@pdfernhout

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

electricessence commented on Apr 25, 2016

@electricessence

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

iby commented on May 3, 2016

@iby

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:

constructor(id:String) {
   var label = I18N.translate(id);
   var icon = IconMap.get(id);
   super(label, icon);
   this.setBackground(this.color);
}

// vs…

constructor(id:String) {
   super(I18N.translate(id), IconMap.get(id));
   this.setBackground(this.color);
}

That limitation doesn't bring in any value. There was an argument on complexity of the checks – doing check for this use before super shouldn't be hard, this is also the same logic used in Swift, which inherits the best from C languages.

added
Effort: ModerateRequires experience with the TypeScript codebase, but feasible. Harder than "Effort: Casual".
and removed on May 17, 2016
DanielRosenwasser

DanielRosenwasser commented on Jul 19, 2016

@DanielRosenwasser
Member

It pretty much looks like this is fixed for 2.0 beta. Can you give it a try @pdfernhout?

martinsik

martinsik commented on Oct 26, 2016

@martinsik

@DanielRosenwasser It's probably all right now. The error message explains what went wrong precisely I think.

This is fine:

class MyClass {
  constructor(public str: string) { }
}

class OtherClass extends MyClass {
  constructor(str: string) {
    var that = str;
    super(str);
  }
}

This is not:

class MyClass {
  constructor(public str: string) { }
}

class OtherClass extends MyClass {
  constructor(public str: string) {
    var that = str;
    super(str);
  }
}
captainjono

captainjono commented on Mar 30, 2017

@captainjono

Could someone tell me why this code is not permitted ?

`export class MatterAccessRevokedForUser extends MatterUserDomainEvent {

constructor();
constructor(tenant: string, fileNumber: string, username: string);
constructor(tenant?: string, fileNumber?: string, username?: string) {
    if (arguments.length === 0) {
        super(null, null, null);
        this.constructor_MatterAccessRevokedForUser_0();
        return;
    }
    super(tenant, fileNumber, username); //ERROR: super must be called before this
    this.constructor_MatterAccessRevokedForUser_1(tenant, fileNumber, username);
}
private constructor_MatterAccessRevokedForUser_0(): void {
}
private constructor_MatterAccessRevokedForUser_1(tenant: string, fileNumber: string, username: string): void {
}

}`

56 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Effort: ModerateRequires experience with the TypeScript codebase, but feasible. Harder than "Effort: Casual".Help WantedYou can do thisSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @dcporter@davidglezz@martinsik@sandersn@trusktr

        Issue actions

          Always allow code before super call when it does not use "this" · Issue #8277 · microsoft/TypeScript