TypeScript - External Helpers Library

 
 
  • Gérald Barré
 

TypeScript lets you use modern ES features while targeting ES5. The compiler rewrites your code to be compatible with the target version, and to do so, it emits helper functions. There are currently 15 such helpers:

  • __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 injected automatically at the top of each file when needed. For example, if you use await in a .ts file, the compiler will emit the following functions:

JavaScript
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 };
    }
};

Depending on the features you use, up to 150 lines of code can be added to every output file. For small projects with fewer than 10 files, this may not matter. However, for large projects with hundreds of files, defining each helper only once makes sense. Reducing output file size also decreases download time for users.

#noEmitHelpers flag

TypeScript 2.1 introduced a flag to prevent the compiler from emitting helpers. When this flag is set, it becomes your responsibility to provide the helpers. The generated code will reference them as if they had been emitted by the compiler.

You can download the helpers using npm:

Shell
npm install tslib

Then, add tslib.js to your HTML page:

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

Then, configure the TypeScript compiler to skip emitting helpers:

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

#importHelpers flag

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

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

This generates the following import at the top of each output file:

JavaScript
var tslib_1 = require("tslib");

#Conclusion

For medium or large projects, it is worth spending a few minutes configuring noEmitHelpers or importHelpers. Doing so reduces output file sizes and improves page load time for your users.

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?