Skip to content

Dangerous Property Initializers in Classes #5987

Description

@kitsonk

This is valid, but seem very dangerous:

class One {
    two() {};
}

class Foo {
    two = this.one.two();
    one = new One();
}

The emit goes in order of declaration which will cause a runtime error:

var One = (function () {
    function One() {
    }
    One.prototype.two = function () { };
    ;
    return One;
})();
var Foo = (function () {
    function Foo() {
        this.two = this.one.two();
        this.one = new One();
    }
    return Foo;
})();

Activity

  1. kitsonk commented on Dec 30, 2015

    @kitsonk
    ContributorAuthor

    I suspect this got lost in the pile. Any thoughts, or is it just and edge case that isn't worth bothering with?

  2. DanielRosenwasser commented on Dec 30, 2015

    @DanielRosenwasser
    Member

    Sorry about that, this past month's been busy and naturally some people are out.

    I wonder if this should fall under the umbrella of #2234.

  3. changed the title [-]Dangerous Parameter Initializers in Classes[/-] [+]Dangerous Property Initializers in Classes[/+] on Dec 30, 2015
  4. kitsonk commented on Dec 30, 2015

    @kitsonk
    ContributorAuthor

    Clearly it is related to #2234, but I would suspect a lot of users would be "surprised" that they have to think about the ordering of a property initializers in a class, although I just checked the ES Stage 1 proposal for class properties and initializers and it appears that this would break there too, so the emit is valid. In that case, stupid is as stupid does and it would logically fall in the realm of use before initialization.

    cc/Adi Dahiya (@adidahiya)

  5. RyanCavanaugh commented on Jan 1, 2016

    @RyanCavanaugh
    Member

    "Order of emit is order of declaration" is a must-have behavior for ES6 compat ES7+ compat as that would almost certainly have the same semantics.

    I don't see why we wouldn't error here, though. We can treat these as if they were let declarations in terms of TDZ rules.

  6. added this to the milestone on Jan 4, 2018
  7. theseyi commented on Mar 15, 2018

    @theseyi

    Is this a similar issue to the ffg being allowed in TS?

    class Test {
      x:any = this.x;
    }

    I can't find any documentation that says you can reference this in a class field / property but TS allows this to compile and emits js, but looking at it seems odd.

    emit:

    var Test = /** @class */ (function () {
        function Test() {
            this.x = this.x;
        }
        return Test;
    }());

    http://www.typescriptlang.org/play/index.html#src=class%20Test%20%7B%0A%20%20x%3Aany%20%3D%20this.x%3B%0A%7D

  8. theseyi commented on Mar 16, 2018

    @theseyi
  9. kitsonk commented on Mar 22, 2018

    @kitsonk
    ContributorAuthor

    I don't know if it is similar. It is valid, though illogical. My opinion would be that it should be an error as well (sort of the same class as use before assigned).

  10. JoshuaKGoldberg commented on Jan 12, 2019

    @JoshuaKGoldberg
    Contributor

    The original code now correctly gives a type checking error! ✨

    class One {
        two() {};
    }
    
    class Foo {
        two = this.one.two();
                   ~~~ // Property 'one' is used before its initialization.ts(2729)
        one = new One();
    }

    However, x: any = this.x; is still allowed but shouldn't be.

  11. added a commit that references this issue on Jan 13, 2019
    cd88f6a
  12. added a commit that references this issue on Apr 5, 2019
    0b3b4ea
  13. chriskrycho commented on May 30, 2019

    @chriskrycho

    Hey folks, the Ember TS crowd just noted an issue with the PR that closed this; see my comment here.

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

      Issue actions