Skip to content
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

Unexpected behaviour #10893

Closed
SimonCsoma opened this issue Sep 13, 2016 · 3 comments
Closed

Unexpected behaviour #10893

SimonCsoma opened this issue Sep 13, 2016 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@SimonCsoma
Copy link

SimonCsoma commented Sep 13, 2016

TypeScript Version: 1.8.0
Code

class Animal {
    constructor() { 
        this.move()
    }
    move(distanceInMeters: number = 0) {
        console.log(distanceInMeters);
    }
}

class Snake extends Animal {
    public variable = 1;
    constructor() { 
        super();

    }
    move(distanceInMeters = 5) {
        console.log(this.variable);
        super.move(distanceInMeters);
    }
}

Expected behavior:
Class variables should alway be accessible and set and should be compiled like this:

    function Snake() {
        this.variable = 1;
        _super.call(this);
    }

Entire compilation:

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Animal = (function () {
    function Animal() {
        this.move();
    }
    Animal.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 0; }
        console.log(distanceInMeters);
    };
    return Animal;
}());
var Snake = (function (_super) {
    __extends(Snake, _super);
    function Snake() {
        this.variable = 1;
        _super.call(this);
    }
    Snake.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 5; }
        console.log(this.variable);
        _super.prototype.move.call(this, distanceInMeters);
    };
    return Snake;
}(Animal));

Actual behavior:
This causes this.variable in the move function of the snake class to always be undefined when constructing a new class.

    function Snake() {
        _super.call(this);
        this.variable = 1;
    }

Entire compilation:

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Animal = (function () {
    function Animal() {
        this.move();
    }
    Animal.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 0; }
        console.log(distanceInMeters);
    };
    return Animal;
}());
var Snake = (function (_super) {
    __extends(Snake, _super);
    function Snake() {
        _super.call(this);
        this.variable = 1;
    }
    Snake.prototype.move = function (distanceInMeters) {
        if (distanceInMeters === void 0) { distanceInMeters = 5; }
        console.log(this.variable);
        _super.prototype.move.call(this, distanceInMeters);
    };
    return Snake;
}(Animal));
@yortus
Copy link
Contributor

yortus commented Sep 13, 2016

I believe the compiler is working correctly here.

In ES6 classes, you cannot reference this before calling super (MDN ref, StackOverflow ref). this will not be bound until after the super() call. You can try it for yourself using node.js or the browser console: referencing this in the constructor before calling super() will throw something like "ReferenceError: this is undefined".

The equivalent ES3/5 downlevelled code has to do things in that order too, otherwise it would not be runtime-equivalent code.

@SimonCsoma
Copy link
Author

SimonCsoma commented Sep 13, 2016

I expect this to complie like this to ES6:

class Animal {
    constructor() { 
        this.move();
    }
    move(distanceInMeters = 0) {
        console.log(distanceInMeters);
    }
}

class _Animal {
    constructor() {
        this.variable = 1
        this.move();
    }
    move(distanceInMeters = 0) {
        console.log(distanceInMeters);
    }
}


class Snake extends _Animal{
    constructor() { 
        super();

    }
    move(distanceInMeters = 5) {
        console.log(this.variable);
        super.move(distanceInMeters);
    }
}

new Snake();

I know this does not make allot of sense on the first view, but since typescript supports public variable I expect it to always be available and this is for now the only way i can produce the expected behaviour.

In my opinion if this cannot be supported it should be removed from the language or a fix shuold be added like this.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Sep 13, 2016
@RyanCavanaugh
Copy link
Member

Duplicate #1617.

@RyanCavanaugh RyanCavanaugh added Duplicate An existing issue was already created and removed Working as Intended The behavior described is the intended behavior; this is not a bug labels Sep 13, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants