What will Typescript transpile when targeting ES5 / ES3?

11,642

Solution 1

TypeScript transpiles but does not polyfill. So one way to think of it is that anything that is not valid syntax in your target will be transpiled to a valid syntax. For example, when using the class keyword with your target set to ES5, it will transpile this:

class Greeter {
}

to this:

var Greeter = /** @class */ (function () {
    function Greeter() {
    }
    return Greeter;
}());

(You can play around more with this here.)

On the other hand, it does not add missing functionality, which you'll have to polyfill yourself. Number.isInteger() is valid ES5 syntax, it's just not functionality that exists in ES5. You can polyfill this yourself by importing babel-polyfill (which uses core-js under the hood) or using a service like polyfill.io.

Note: don't confuse the lib option with polyfills. This does not polyfill features. It simply tells TypeScript to act as if features from those ES versions are present, so it will type check them appropriately. You still need to handle the polyfill piece yourself for browsers that you support. If you don't specify the appropriate libs, TypeScript will complain that it doesn't know what Number.isInteger() represents.

I'm not aware of a comprehensive list of which features TypeScript transpiles, but you can see a table for TypeScript+core-js polyfills here. More reading on polyfills vs transpilation here.

Solution 2

The compiler supports features based on the lib that you tell it to use.
There are two ways to control which lib the compiler will use, by using the target and lib compiler options.

As it's written in the above link:

If --lib is not specified a default library is injected. The default library injected is:
► For --target ES5: DOM,ES5,ScriptHost
► For --target ES6: DOM,ES6,DOM.Iterable,ScriptHost

All of the different libs are part of the project.

If you are targeting es3 or es5 then you can't use Number.isInteger() as it's (as you stated) a es6 feature.
If you have a polyfil for that then you can still target es5 with the es6 lib:

--target es5 --lib DOM,ES6,ScriptHost

Or you can just copy the definition for the lib.es6.d.ts:

interface NumberConstructor {
    isInteger(number: number): boolean;
}

The reason that you can use things like let, const, for/of regardless of the target is that the compiler knows how to produce equivalent code even when the feature isn't supported for the chosen target.

For example:

const arr = [1, 2, 3];
for (let num of arr) {}

Is compiled to:

var arr = [1, 2, 3];
for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) {
    var num = arr_1[_i];
}

If no target is specified.
As you can see, the const and let are turned into vars, and the for/in is turned into a regular for.

Number.isInteger() is something different, it's a functionality that doesn't exist in certain targets, like Promise and 'Symbol`.
The compiler won't add the polyfill, it's up to you to add it and then tell the compiler that it's there.

Share:
11,642

Related videos on Youtube

JoshMB
Author by

JoshMB

Updated on May 16, 2020

Comments

  • JoshMB
    JoshMB almost 4 years

    I'm trying to understand when the Typescript compiler will transpile code to make it compatible with my specified target ECMAScript version (ES5 or ES3).

    For example, TSC will transpile for(var int of intArray) fine, but it doesn't transpile Number.isInteger() (which is an ES6 feature, according to w3schools).

    Number.isInteger() isn't supported in IE < 11.0, so this is a problem. Visual Studio (and VS Code) don't provide warnings of incompatibility, and it doesn't get transpiled.

    What can I expect to get transpiled, and what won't? I initially expected that everything would be transpiled, so that I wouldn't have to keep track of things like this, but that doesn't seem to be the case.

    • JoshMB
      JoshMB about 7 years
      If this is the case, it would be nice if the IDE would alert me to the incompatibility of my code with my targeted ECMAScript version. I started using Number.isInteger() because Visual Studio offered it to me, and only later discovered that many (relatively modern) browsers don't support it. Not sure what other "landmines" await!

Related