TypeScript - External Helpers Library

TypeScript allows you to use ES next features while targeting ES5. The compiler will rewrite the code to be compatible with the targeted version. To rewrite some functionnalities, the compiler emits helper functions. There are currently 15 functions:

  • __extends for inheritance
  • __awaiter and __generator for async/await
  • __assign, __spread and __rest for object spread and rest
  • __decorate, __param and __metadata for decorators

These functions are added automatically at the beginning of each files when needed. For instance, if you use await in a ts file, the compiler will emit the following functions:

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [0, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};

You can add up to 150 lines of code in every js files depending on the features you use. If you have less then 10 files, maybe you don't care. But if you are working on a large projects with hundreds of files, you may want to declare the helper function only once. Keep in mind that reducing the size of the js files will reduce the time required to download them for the clients.

noEmitHelpers flag

TypeScript 2.1 introduced a new flag to prevent the compiler from generating the helpers. This means this is your responsability to add the helpers. The generated code will use them as if it was emitted by the compiler.

You can download the helpers using npm:

npm install tslib

Then, add the tslib.js in you html page:

<html>
    <head>
        <script src="node_modules/tslib/tslib.js"></script>
        <script src="file.js"></script>
    </head>
    <body>
    </body>
</html>

Then, you must configure the TypeScript compiler to not emit the helpers:

{
    "compilerOptions": {
        "noEmitHelpers": true
    }
}

importHelpers flags

If you are using modules, you can instruct the compiler to import tslib as a module:

{
    "compilerOptions": {
        "importHelpers": true,
        "module": "commonjs"
    }
}

This will generate the following code at the beginning of the js file:

var tslib_1 = require("tslib");

Conclusion

If you are working on a medium or large project, you should take a few minutes to configure the noEmitHelpers or importHelpers options. This will reduce the size of the js files and so, improve the loading time of your pages.

Leave a reply