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

Add ability to specify the external __extends function #2009

Closed
Taritsyn opened this issue Feb 11, 2015 · 10 comments
Closed

Add ability to specify the external __extends function #2009

Taritsyn opened this issue Feb 11, 2015 · 10 comments
Labels
Fixed A PR has been merged for this issue Suggestion An idea for TypeScript

Comments

@Taritsyn
Copy link

Currently when implementing of class inheritance in the output JS-file automatically added the following code:

var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};

And calls of the following kind:

__extends(MyClass, _super);

In the presence of large amount of TS-files in the project, this leads to a significant increase size of concatenated file (especially when using AMD-modules).

It would be nice to add a new compiler option (it can be called externalExtendsFunction), which would be allow to specify the name of analog __extends function from external script. For example, if we set to the externalExtendsFunction option a value equal to util.extends, then the __extends function code will not be generated in the JS-file and its calls will be as follows:

util.extends(MyClass, _super);
@danquirk
Copy link
Member

Are you using the latest bits? #1350 was fixed by #1356 which should stop multiple __extends from being emitted often. The implementation of __extends already permits being overridden by your own (if this.__extends exists).

@Taritsyn
Copy link
Author

I build tsc.js from commit f2c98ba95eebfd544aa17d479ed574d59bd7bef1 and tried to compile an example from the "Don't emit __extends if one is already in scope #1356" issue. And I got the following result:

var __extends = this.__extends || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
var M;
(function (M) {
    M.__extends = function () { };
    var A = (function () {
        function A() {
        }
        return A;
    })();
    var B = (function (_super) {
        __extends(B, _super);
        function B() {
            _super.apply(this, arguments);
        }
        return B;
    })(A);
})(M || (M = {}));

Then I found out, that this pull request was not merged to the master branch. But such a solution is unlikely to be help when compiling of external modules with a single export:

class A {
    foo(): void {
        alert('foo');
    }
}

class B extends A {
    bar(): void {
        alert('bar');
    }
}

export = B;

I use a single exports when creating a view models in Durandal. Here we need a more comprehensive solution of problem (similar to what I suggested).

By the way, I noticed that even if the target option equals to es6, then class inheritance anyway is implemented by using the __extends function instead of using the native ECMAScript 6 class inheritance.

@danquirk
Copy link
Member

Ah, sorry about that, I also didn't notice we never merged that. There're apparently some additional cases that aren't handled by that PR yet. I logged #2022 for the ES6 part.

@tomitrescak
Copy link

Hi, the documentation says that "noEmitHelpers" flag is supported now, but using it with 1.5.0-Beta does not do anything? Is there any particular release I should be using? Thanks.

@mhegazy
Copy link
Contributor

mhegazy commented Jun 11, 2015

This was added after 1.5-beta, so it should be in the next release 1.5.2

@tomitrescak
Copy link

Thanks for the info! Any estimate on when it will be?

@mhegazy
Copy link
Contributor

mhegazy commented Jun 11, 2015

we usually like to stabilize a release for a few weeks before it is released. We are not adding any more features just big fixes at the point. So hopefully soon.

@mikemorton
Copy link

noEmitHelpers is working well for me, but I was curious if there was a pre-created Helpers File that would be easy for me to simply include in my project?

@mhegazy
Copy link
Contributor

mhegazy commented Aug 31, 2015

@mikemorton there is not one, but here is what i would put:

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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
    switch (arguments.length) {
        case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
        case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
        case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
    }
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};

var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) {
    return new Promise(function (resolve, reject) {
        generator = generator.call(thisArg, _arguments);
        function cast(value) { return value instanceof Promise && value.constructor === Promise ? value : new Promise(function (resolve) { resolve(value); }); }
        function onfulfill(value) { try { step("next", value); } catch (e) { reject(e); } }
        function onreject(value) { try { step("throw", value); } catch (e) { reject(e); } }
        function step(verb, value) {
            var result = generator[verb](value);
            result.done ? resolve(result.value) : cast(result.value).then(onfulfill, onreject);
        }
        step("next", void 0);
    });
};

@mhegazy mhegazy closed this as completed Aug 31, 2015
@mhegazy
Copy link
Contributor

mhegazy commented Aug 31, 2015

this is handled with the --noEmitHelpers as stated above.

@mhegazy mhegazy added the Fixed A PR has been merged for this issue label Aug 31, 2015
@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Fixed A PR has been merged for this issue Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

5 participants