TypeScript is a highly configurable language.
It comes with over a hundred compiler options that can be provided via the command-line to tsc and/or in a "TSConfig" configuration file (by default, tsconfig.json).
TypeScript's compiler options are documented at aka.ms/tsconfig.
compilerOptions.target in particular can be an important configuration option for your project.
It specifies which ECMAScript version your project's output JavaScript code must support.
You can specify target in your TSConfig as the string name of an ECMAScript version, such as "es5"or"es2021":
jsonc
jsonc
This article explores what target influences and why that's useful.
Let's dig in!
ECMAScript is the standard that JavaScript is based on. Each year, a new version is released that adds features to the language. Runtimes such as browsers and Node.js are constantly updating to support those newer features.
What TSConfig target Does
compilerOptions.target influences three facets of how TypeScript interacts with your code:
- If TypeScript is being used to transpile your source files to JavaScript, it specifies what syntax must be transpiled down to support older ECMAScript language versions.
- Some syntax features are only allowed in newer targets.
- compilerOptions.libdefaults to including global API type definitions corresponding to your target.
Let's cover each of those benefits in more detail.
1. Smaller Output JavaScript
Regardless of the transpiler you're using to generate JavaScript code, supporting relatively newer ECMAScript targets means your code will stay relatively more similar to its source. Older ECMAScript targets necessitate transpiling newer JavaScript syntax down to equivalent older syntax.
Take the following async function written in JavaScript:
js
js
The equivalent runtime code for just that function -ignoring tslib helpers- is much larger and much less readable:
js
js
That's a lot more code, and quite incomprehensible! Choosing a newer target would make sure emitted JavaScript stays lean and readable.
2. Unlocked Newer Syntax
New forms of syntax added in newer ECMAScript versions generally try to be backwards-compatible with older ECMAScript versions via transpiling.
The previous async function valueAfterDelay code blocks are an example: they show async being turned into code runnable in very old environments.
Some newer forms of syntax, however, can't be transpiled down for support.
TypeScript will report a syntax error if you try to use one that can't be supported by your target.
Those syntax features include property accessors and class # private identifiers:
tscontainer = {getAccessors are only available when targeting ECMAScript 5 and higher.1056Accessors are only available when targeting ECMAScript 5 and higher.() { property return "hi!";},};classRandomBox {Private identifiers are only available when targeting ECMAScript 2015 and higher.18028Private identifiers are only available when targeting ECMAScript 2015 and higher.#value =Math .random ();getValue () {return this.#value;}}
tscontainer = {getAccessors are only available when targeting ECMAScript 5 and higher.1056Accessors are only available when targeting ECMAScript 5 and higher.() { property return "hi!";},};classRandomBox {Private identifiers are only available when targeting ECMAScript 2015 and higher.18028Private identifiers are only available when targeting ECMAScript 2015 and higher.#value =Math .random ();getValue () {return this.#value;}}
Projects stuck on older ECMAScript targets can't use those nice new features.
When using a newer target, those syntax features are allowed by TypeScript's syntax checks.
3. Unlocked Lib Features
ECMAScript versions also often specify new APIs, such as methods on built-in classes.
TypeScript's lib compiler option allows you to specify what era of runtime ECMAScript features are supposed to be available when your code runs.
lib defaults to including DOM (browser) types along with the same year as your compilerOptions.target.
As an example, String.prototype.replaceAll is only natively available in ES2021 environments and newer.
Using it in a project with a target lower than "es2021" and the default lib would result in a TypeScript type error:
tsvalues = "abc abc abc";Property 'replaceAll' does not exist on type 'string'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2021' or later.2550Property 'replaceAll' does not exist on type 'string'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2021' or later.values .("a", "!"); replaceAll 
tsvalues = "abc abc abc";Property 'replaceAll' does not exist on type 'string'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2021' or later.2550Property 'replaceAll' does not exist on type 'string'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2021' or later.values .("a", "!"); replaceAll 
By increasing compilerOptions.target to a value like "es2022" (which increases lib as a result), TypeScript recognizes that APIs such as String.prototype.replaceAll are available at runtime:
tsvalues = "abc abc abc";values .replaceAll ("a", "!"); // ok
tsvalues = "abc abc abc";values .replaceAll ("a", "!"); // ok
Note that is possible to polyfill newer ECMAScript APIs into older environments. core-js is a popular library for JavaScript polyfills.
Some projects that use polyfills specify a lib higher than their target because they can rely on the APIs being polyfilled in.
TypeScript recognizes global API types corresponding to the lib:
tsvalues = "abc abc abc";values .replaceAll ("a", "!"); // Ok
tsvalues = "abc abc abc";values .replaceAll ("a", "!"); // Ok
target Might Not Impact Your Runtime Code
We should also note that TypeScript's target only impacts your runtime code if you're using TypeScript to transpile your source files to JavaScript.
If you're using another tool to transpile, such as Babel, ESBuild, or SWC, then that tool's settings will be what determines the syntax used in your output JavaScript code.
Still, specifying target can still be useful.
compilerOptions.lib defaults to including global type definitions corresponding to your compilerOptions.target.
If you're not customizing your lib compiler option, then specifying target can still impact with global APIs TypeScript recognizes you can use.
Choosing a target
Learning TypeScript recommends using the highest possible ECMAScript target supported by all the environment(s) your code will be run in.
In other words, you'll want to pick the oldest ECMAScript environment target that your code might run in - and no older.
Picking as new a compilerOptions.target as possible improves both the output code your users run and your development experience of using TypeScript.
The kangax compatibility table is an excellent tool for determining which features are supported in each environment. It includes a list of all the runtime features added in each ECMAScript version, along with whether they're supported in many popular JavaScript environments.
Browser Apps
As of 2023, the vast majority of browsers support at least ES2021, including:
- Chrome >=99 (released March 2022)
- Edge >=99 (released February 2022)
- Firefox >=98 (released March 2022)
- Safari >=15.2* (released December 2021)
target.Unless you intentionally support older browsers, such as for corporate or education users, you can pick ES2021.
If you do need to support older browsers, consult the kangax compatibility table to see what ECMAScript features they support.
Many developers also utilize caniuse.com for checking specific language feature support in browsers.
It can show which browser versions support a feature.
For example, caniuse.com/?search=replaceAll shows String.prototype.replaceAll as being available in Chrome/Edge (Desktop) 85, Safari (Mac) 13.1, Firefox 77, Opera 71, Chrome (Android) 111, and Safari (iOS) 13.4.
Server Apps
As of 2023, the vast majority of servers also support at least ES2021. That includes:
- Deno 1.24
- Node 16.11 and newer supported versions of Node per the Node release schedule
If you do need to run on older environments, consult the kangax compatibility table to see what ECMAScript features they support.
Next Steps
By now, you've seen why a relatively recent compilerOptions.target is beneficial, as well as how to determine which target your code can run with (most likely at least ES2021).
Knowing how to properly configure each compiler option in your TSConfig can help optimize your development flow and resultant application.
See aka.ms/tsconfig for the TSConfig full reference docs.
jsonc
jsonc
Learning TypeScript's Chapter 13: Configuration Options also goes over many of the important configuration options provided by TypeScript. Consider reading that chapter for an overview of how many of them fit together.
Got your own TypeScript questions? Tweet @LearningTSBook and the answer might become an article too!