Which version of EcmaScript should I use in the TypeScript configuration

 
 
  • Gérald Barré

TypeScript can compile most ESNext features down to ES3, ES5, ES6, ES2016, or ES2017. You can also target ESNext directly. So, which version should you target?

#Why you should use the highest possible version?

Targeting the highest version lets you write shorter, more readable code and use modern features like async/await, for..of, and spread. It also makes debugging easier. For example, TypeScript rewrites async/await as a state machine, which makes the call stack harder to follow and stepping through code more tedious. Source maps can help, but they do not solve all issues. You can also blackbox certain scripts in the debugger. For instance, you can blackbox tslib if you import TypeScript helpers.

If you can target ESNext, do it! Unfortunately, this is not always possible. Let's see how to choose the right version.

#Select your target JS runtime

First, identify the runtimes you need to support: a specific web browser, Node.js, or Electron. Your choice determines which JavaScript features are available. For instance, if you target Electron, you know its Chromium version and can check which features it supports. Node.js also uses V8 (the Chromium JavaScript engine), making it straightforward to determine supported features. For web browsers, it is more complex since you may need to support several browsers and versions.

You can check which features are supported by web browsers and JS runtimes here: https://kangax.github.io/compat-table/es6. Tip: you can change the ES version at the top.

For example, targeting IE11 requires ES5. For Node.js, MS Edge, or Chromium, ES6 is sufficient.

Once you know which version to use, update tsconfig.json to reflect your decision:

JSON
{
    "compilerOptions": {
        "target": "ES2016" // "ES3" (default), "ES5", "ES6"/"ES2015", "ES2016", "ES2017" or "ESNext".
    }
}

#Which libraries to target?

Changing the target version also affects which built-in libraries are available. For example, targeting ES5 means Promise is not included. However, Promise does not require engine-level support. You can polyfill it with a library like bluebird. This means you can target ES5 and still use Promises by including an external library. The same applies to Array.include and many other methods.

TypeScript lets you specify which libraries are available via the lib option in tsconfig.json:

JSON
{
    "compilerOptions": {
        "lib": [
            "ES5",
            "ES2015.Promise",
            "ES2016.Array.Include"
        ],
    }
}

You can find the list of available libraries in the TypeScript documentation.

You can also read my previous post on dynamically importing polyfills.

#Development vs Release configurations?

As mentioned in the introduction, targeting a higher ECMAScript version can improve your debugging experience. It may be worth maintaining two separate configurations: one for development and one for release. For example, the development configuration can target ESNext since you debug on a modern browser, while the release configuration targets ES5 for broader browser compatibility.

TypeScript supports configuration inheritance. You can create a base tsconfig.json with shared settings and a tsconfig.dev.json that extends it. Build with tsc tsconfig.dev.json. You can read the documentation about configuration inheritance for more information.

#Babel

If you use webpack, gulp, or another build tool, consider the Babel option. The idea is to configure TypeScript to target ESNext and let Babel handle the transpilation to a lower version. According to the compatibility table, Babel can transpile more features to older ES versions than TypeScript alone. With webpack, you can also automatically inject polyfills using a plugin like webpack-polyfill-injector.

#Conclusion

Choose the configuration that maximizes your productivity while running correctly on your target browsers and runtimes.

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

Follow me:
Enjoy this blog?