- Project Options
- Allow JS -
allowJs
- Check JS -
checkJs
- Composite -
composite
- Declaration -
declaration
- Declaration Map -
declarationMap
- Downlevel Iteration -
downlevelIteration
- Import Helpers -
importHelpers
- Incremental -
incremental
- Isolated Modules -
isolatedModules
- JSX -
jsx
- For example
- Lib -
lib
- High Level libraries
- Individual library components
- Module -
module
None
- No Emit -
noEmit
- Out Dir -
outDir
- Out File -
outFile
- Plugins -
plugins
- Remove Comments -
removeComments
- Root Dir -
rootDir
- Source Map -
sourceMap
- Target -
target
- TS Build Info File -
tsBuildInfoFile
- Allow JS -
Project Options
These settings are used to define the runtime expectations of your project, how and where you want the JavaScript to be emitted and the level of integration you want with existing JavaScript code.
Allow JS - allowJs
Allow JavaScript files to be imported inside your project, instead of just .ts
and .tsx
files. For example, this JS file:
Try
// @filename: card.jsexport constdefaultCardDeck = "Heart";
When imported into a TypeScript file will raise an error:
// @filename: index.tsimport {defaultCardDeck } from "./card";Try
console .log (defaultCardDeck );
Imports fine with allowJs
enabled:
// @filename: index.tsimport {defaultCardDeck } from "./card";Try
console .log (defaultCardDeck );
This flag can be used as a way to incrementally add TypeScript files into JS projects by allowing the .ts
and .tsx
files to live along-side existing JavaScript files.
Default:
false
Related:
Released:
Check JS - checkJs
Works in tandem with allowJs
. When checkJs
is enabled then errors are reported in JavaScript files. This is the equivalent of including // @ts-check
at the top of all JavaScript files which are included in your project.
For example, this is incorrect JavaScript according to the parseFloat
type definition which comes with TypeScript:
js
// parseFloat only takes a stringmodule.exports.pi = parseFloat(3.124);
When imported into a TypeScript module:
// @filename: constants.jsmodule .exports .pi =parseFloat (3.124);Try
// @filename: index.tsimport {pi } from "./constants";console .log (pi );
You will not get any errors. However, if you turn on checkJs
then you will get error messages from the JavaScript file.
// @filename: constants.jsArgument of type 'number' is not assignable to parameter of type 'string'.2345Argument of type 'number' is not assignable to parameter of type 'string'.module .exports .pi =parseFloat (3.124);Try
// @filename: index.tsimport {pi } from "./constants";console .log (pi );
Default:
false
Related:
Released:
Composite - composite
The composite
option enforces certain constraints which make it possible for build tools (including TypeScript itself, under --build
mode) to quickly determine if a project has been built yet.
When this setting is on:
- The
rootDir
setting, if not explicitly set, defaults to the directory containing thetsconfig.json
file. - All implementation files must be matched by an
include
pattern or listed in thefiles
array. If this constraint is violated,tsc
will inform you which files weren’t specified. declaration
defaults totrue
You can find documentation on TypeScript projects in the handbook.
Default:
true
Related:
Released:
Declaration - declaration
Generate .d.ts
files for every TypeScript or JavaScript file inside your project. These .d.ts
files are type definition files which describe the external API of your module. With .d.ts
files, tools like TypeScript can provide intellisense and accurate types for un-typed code.
When declaration
is set to true
, running the compiler with this TypeScript code:
Try
export lethelloWorld = "hi";
Will generate an index.js
file like this:
Try
export let helloWorld = "hi";
With a corresponding helloWorld.d.ts
:
Try
export declare let helloWorld: string;
When working with .d.ts
files for JavaScript files you may want to use emitDeclarationOnly
or use outDir
to ensure that the JavaScript files are not overwritten.
Default:
false
Related:
Released:
Declaration Map - declarationMap
Generates a source map for .d.ts
files which map back to the original .ts
source file. This will allow editors such as VS Code to go to the original .ts
file when using features like Go to Definition.
You should strongly consider turning this on if you’re using project references.
Default:
false
Released:
Downlevel Iteration - downlevelIteration
Downleveling is TypeScript’s term for transpiling to an older version of JavaScript. This flag is to enable support for a more accurate implementation of how modern JavaScript iterates through new concepts in older JavaScript runtimes.
ECMAScript 6 added several new iteration primitives: the for / of
loop (for (el of arr)
), Array spread ([a, ...b]
), argument spread (fn(...args)
), and Symbol.iterator
. --downlevelIteration
allows for these iteration primitives to be used more accurately in ES5 environments if a Symbol.iterator
implementation is present.
Example: Effects on for / of
With this TypeScript code:
Try
conststr = "Hello!";for (consts ofstr ) {console .log (s );}
Without downlevelIteration
enabled, a for / of
loop on any object is downleveled to a traditional for
loop:
Try
"use strict";var str = "Hello!";for (var _i = 0, str_1 = str; _i < str_1.length; _i++) {var s = str_1[_i];console.log(s);}
This is often what people expect, but it’s not 100% compliant with ECMAScript iteration protocol. Certain strings, such as emoji (😜), have a .length
of 2 (or even more!), but should iterate as 1 unit in a for-of
loop. See this blog post by Jonathan New for a longer explanation.
When downlevelIteration
is enabled, TypeScript will use a helper function that checks for a Symbol.iterator
implementation (either native or polyfill). If this implementation is missing, you’ll fall back to index-based iteration.
Try
"use strict";var __values = (this && this.__values) || function(o) {var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;if (m) return m.call(o);if (o && typeof o.length === "number") return {next: function () {if (o && i >= o.length) o = void 0;return { value: o && o[i++], done: !o };}};throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");};var e_1, _a;var str = "Hello!";try {for (var str_1 = __values(str), str_1_1 = str_1.next(); !str_1_1.done; str_1_1 = str_1.next()) {var s = str_1_1.value;console.log(s);}}catch (e_1_1) { e_1 = { error: e_1_1 }; }finally {try {if (str_1_1 && !str_1_1.done && (_a = str_1.return)) _a.call(str_1);}finally { if (e_1) throw e_1.error; }}
You can use tslib via importHelpers
to reduce the amount of inline JavaScript too:
Try
"use strict";var __values = (this && this.__values) || function(o) {var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;if (m) return m.call(o);if (o && typeof o.length === "number") return {next: function () {if (o && i >= o.length) o = void 0;return { value: o && o[i++], done: !o };}};throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");};var e_1, _a;var str = "Hello!";try {for (var str_1 = __values(str), str_1_1 = str_1.next(); !str_1_1.done; str_1_1 = str_1.next()) {var s = str_1_1.value;console.log(s);}}catch (e_1_1) { e_1 = { error: e_1_1 }; }finally {try {if (str_1_1 && !str_1_1.done && (_a = str_1.return)) _a.call(str_1);}finally { if (e_1) throw e_1.error; }}
Note: enabling downlevelIteration
does not improve compliance if Symbol.iterator
is not present in the runtime.
Example: Effects on Array Spreads
This is an array spread:
js
// Make a new array who elements are 1 followed by the elements of arr2const arr = [1, ...arr2];
Based on the description, it sounds easy to downlevel to ES5:
js
// The same, right?const arr = [1].concat(arr2);
However, this is observably different in certain rare cases. For example, if an array has a “hole” in it, the missing index will create an own property if spreaded, but will not if built using concat
:
js
// Make an array where the '1' element is missinglet missing = [0, , 1];let spreaded = [...missing];let concated = [].concat(missing);// true"1" in spreaded;// false"1" in concated;
Just as with for / of
, downlevelIteration
will use Symbol.iterator
(if present) to more accurately emulate ES 6 behavior.
Default:
false
Related:
Released:
Import Helpers - importHelpers
For certain downleveling operations, TypeScript uses some helper code for operations like extending class, spreading arrays or objects, and async operations. By default, these helpers are inserted into files which use them. This can result in code duplication if the same helper is used in many different modules.
If the importHelpers
flag is on, these helper functions are instead imported from the tslib module. You will need to ensure that the tslib
module is able to be imported at runtime. This only affects modules; global script files will not attempt to import modules.
For example, with this TypeScript:
ts
export function fn(arr: number[]) {const arr2 = [1, ...arr];}
Turning on downlevelIteration
and importHelpers
is still false:
Try
var __read = (this && this.__read) || function (o, n) {var m = typeof Symbol === "function" && o[Symbol.iterator];if (!m) return o;var i = m.call(o), r, ar = [], e;try {while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);}catch (error) { e = { error: error }; }finally {try {if (r && !r.done && (m = i["return"])) m.call(i);}finally { if (e) throw e.error; }}return ar;};var __spreadArray = (this && this.__spreadArray) || function (to, from) {for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)to[j] = from[i];return to;};export function fn(arr) {var arr2 = __spreadArray([1], __read(arr));}
Then turning on both downlevelIteration
and importHelpers
:
Try
import { __read, __spreadArray } from "tslib";export function fn(arr) {var arr2 = __spreadArray([1], __read(arr));}
You can use noEmitHelpers
when you provide your own implementations of these functions.
Default:
false
Related:
Incremental - incremental
Tells TypeScript to save information about the project graph from the last compilation to files stored on disk. This creates a series of .tsbuildinfo
files in the same folder as your compilation output. They are not used by your JavaScript at runtime and can be safely deleted. You can read more about the flag in the 3.4 release notes.
To control which folders you want to the files to be built to, use the config option tsBuildInfoFile
.
Default:
true
ifcomposite
,false
otherwiseRelated:
Released:
Isolated Modules - isolatedModules
While you can use TypeScript to produce JavaScript code from TypeScript code, it’s also common to use other transpilers such as Babel to do this. However, other transpilers only operate on a single file at a time, which means they can’t apply code transforms that depend on understanding the full type system. This restriction also applies to TypeScript’s ts.transpileModule
API which is used by some build tools.
These limitations can cause runtime problems with some TypeScript features like const enum
s and namespace
s. Setting the isolatedModules
flag tells TypeScript to warn you if you write certain code that can’t be correctly interpreted by a single-file transpilation process.
It does not change the behavior of your code, or otherwise change the behavior of TypeScript’s checking and emitting process.
Some examples of code which does not work when isolatedModules
is enabled.
Exports of Non-Value Identifiers
In TypeScript, you can import a type and then subsequently export it:
import {someType ,someFunction } from "someModule";
someFunction ();Try
export {someType ,someFunction };
Because there’s no value for someType
, the emitted export
will not try to export it (this would be a runtime error in JavaScript):
js
export { someFunction };
Single-file transpilers don’t know whether someType
produces a value or not, so it’s an error to export a name that only refers to a type.
Non-Module Files
If isolatedModules
is set, all implementation files must be modules (which means it has some form of import
/export
). An error occurs if any file isn’t a module:
Try
'index.ts' cannot be compiled under '--isolatedModules' because it is considered a global script file. Add an import, export, or an empty 'export {}' statement to make it a module.1208'index.ts' cannot be compiled under '--isolatedModules' because it is considered a global script file. Add an import, export, or an empty 'export {}' statement to make it a module.function fn () {}
This restriction doesn’t apply to .d.ts
files
References to const enum
members
In TypeScript, when you reference a const enum
member, the reference is replaced by its actual value in the emitted JavaScript. Changing this TypeScript:
Try
declare const enumNumbers {Zero = 0,One = 1,}console .log (Numbers .Zero +Numbers .One );
To this JavaScript:
Try
"use strict";console.log(0 + 1);
Without knowledge of the values of these members, other transpilers can’t replace the references to Numbers
, which would be a runtime error if left alone (since there are no Numbers
object at runtime). Because of this, when isolatedModules
is set, it is an error to reference an ambient const enum
member.
Default:
false
JSX - jsx
Controls how JSX constructs are emitted in JavaScript files. This only affects output of JS files that started in .tsx
files.
react
: Emit.js
files with JSX changed to the equivalentReact.createElement
callsreact-jsx
: Emit.js
files with the JSX changed to_jsx
callsreact-jsxdev
: Emit.js
files with the JSX to_jsx
callspreserve
: Emit.jsx
files with the JSX unchangedreact-native
: Emit.js
files with the JSX unchanged
For example
This sample code:
tsx
export const helloWorld = () => <h1>Hello world</h1>;
Default: "react"
Try
export const helloWorld = () => React.createElement("h1", null, "Hello world");
Preserve: "preserve"
Try
export const helloWorld = () => <h1>Hello world</h1>;
React Native: "react-native"
Try
export const helloWorld = () => <h1>Hello world</h1>;
React 17 transform: "react-jsx"
[1]
Try
import { jsx as _jsx } from "react/jsx-runtime";export const helloWorld = () => _jsx("h1", { children: "Hello world" }, void 0);
React 17 dev transform: "react-jsxdev"
[1]
Try
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";const _jsxFileName = "/home/runner/work/TypeScript-Website/TypeScript-Website/packages/typescriptlang-org/index.tsx";export const helloWorld = () => _jsxDEV("h1", { children: "Hello world" }, void 0, false, { fileName: _jsxFileName, lineNumber: 7, columnNumber: 32 }, this);
Default:
undefined
Allowed:
react
,react-jsx
,react-jsxdev
,react-native
,preserve
Related:
Released:
Lib - lib
TypeScript includes a default set of type definitions for built-in JS APIs (like Math
), as well as type definitions for things found in browser environments (like document
). TypeScript also includes APIs for newer JS features matching the target
you specify; for example the definition for Map
is available if target
is ES6
or newer.
You may want to change these for a few reasons:
- Your program doesn’t run in a browser, so you don’t want the
"dom"
type definitions - Your runtime platform provides certain JavaScript API objects (maybe through polyfills), but doesn’t yet support the full syntax of a given ECMAScript version
- You have polyfills or native implementations for some, but not all, of a higher level ECMAScript version
High Level libraries
Name | Contents |
---|---|
ES5 | Core definitions for all ES3 and ES5 functionality |
ES2015 | Additional APIs available in ES2015 (also known as ES6) - array.find , Promise , Proxy , Symbol , Map , Set , Reflect , etc. |
ES6 | Alias for “ES2015” |
ES2016 | Additional APIs available in ES2016 - array.include , etc. |
ES7 | Alias for “ES2016” |
ES2017 | Additional APIs available in ES2017 - Object.entries , Object.values , Atomics , SharedArrayBuffer , date.formatToParts , typed arrays, etc. |
ES2018 | Additional APIs available in ES2018 - async iterables, promise.finally , Intl.PluralRules , rexexp.groups , etc. |
ES2019 | Additional APIs available in ES2019 - array.flat , array.flatMap , Object.fromEntries , string.trimStart , string.trimEnd , etc. |
ES2020 | Additional APIs available in ES2020 - string.matchAll , etc. |
ESNext | Additional APIs available in ESNext - This changes as the JavaScript specification evolves |
DOM | DOM definitions - window , document , etc. |
WebWorker | APIs available in WebWorker contexts |
ScriptHost | APIs for the Windows Script Hosting System |
Individual library components
Name |
---|
DOM.Iterable |
ES2015.Core |
ES2015.Collection |
ES2015.Generator |
ES2015.Iterable |
ES2015.Promise |
ES2015.Proxy |
ES2015.Reflect |
ES2015.Symbol |
ES2015.Symbol.WellKnown |
ES2016.Array.Include |
ES2017.object |
ES2017.Intl |
ES2017.SharedMemory |
ES2017.String |
ES2017.TypedArrays |
ES2018.Intl |
ES2018.Promise |
ES2018.RegExp |
ES2019.Array |
ES2019.Full |
ES2019.Object |
ES2019.String |
ES2019.Symbol |
ES2020.Full |
ES2020.String |
ES2020.Symbol.wellknown |
ESNext.AsyncIterable |
ESNext.Array |
ESNext.Intl |
ESNext.Symbol |
This list may be out of date, you can see the full list in the TypeScript source code.
Module - module
Sets the module system for the program. See the Modules reference page for more information. You very likely want "CommonJS"
for node projects.
Changing module
affects moduleResolution
which also has a reference page.
Here’s some example output for this file:
// @filename: index.tsimport {valueOfPi } from "./constants";Try
export consttwoPi =valueOfPi * 2;
CommonJS
Try
"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.twoPi = void 0;const constants_1 = require("./constants");exports.twoPi = constants_1.valueOfPi * 2;
UMD
Try
(function (factory) {if (typeof module === "object" && typeof module.exports === "object") {var v = factory(require, exports);if (v !== undefined) module.exports = v;}else if (typeof define === "function" && define.amd) {define(["require", "exports", "./constants"], factory);}})(function (require, exports) {"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.twoPi = void 0;const constants_1 = require("./constants");exports.twoPi = constants_1.valueOfPi * 2;});
AMD
Try
define(["require", "exports", "./constants"], function (require, exports, constants_1) {"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.twoPi = void 0;exports.twoPi = constants_1.valueOfPi * 2;});
System
Try
System.register(["./constants"], function (exports_1, context_1) {"use strict";var constants_1, twoPi;var __moduleName = context_1 && context_1.id;return {setters: [function (constants_1_1) {constants_1 = constants_1_1;}],execute: function () {exports_1("twoPi", twoPi = constants_1.valueOfPi * 2);}};});
ESNext
Try
import { valueOfPi } from "./constants";export const twoPi = valueOfPi * 2;
ES2020
Try
import { valueOfPi } from "./constants";export const twoPi = valueOfPi * 2;
None
Try
"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.twoPi = void 0;const constants_1 = require("./constants");exports.twoPi = constants_1.valueOfPi * 2;
Allowed:
CommonJS
(default iftarget
isES3
orES5
),
,ES6
/ES2015
(synonymous, default fortarget
ES6
and higher),
,ES2020
,None
,UMD
,AMD
,System
,ESNext
Related:
Released:
No Emit - noEmit
Do not emit compiler output files like JavaScript source code, source-maps or declarations.
This makes room for another tool like Babel, or swc to handle converting the TypeScript file to a file which can run inside a JavaScript environment.
You can then use TypeScript as a tool for providing editor integration, and as a source code type-checker.
Default:
false
Out Dir - outDir
If specified, .js
(as well as .d.ts
, .js.map
, etc.) files will be emitted into this directory. The directory structure of the original source files is preserved; see rootDir if the computed root is not what you intended.
If not specified, .js
files will be emitted in the same directory as the .ts
files they were generated from:
sh
$ tscexample├── index.js└── index.ts
With a tsconfig.json
like this:
{"": {"": "dist"}}
Running tsc
with these settings moves the files into the specified dist
folder:
sh
$ tscexample├── dist│ └── index.js├── index.ts└── tsconfig.json
Out File - outFile
If specified, all global (non-module) files will be concatenated into the single output file specified.
If module
is system
or amd
, all module files will also be concatenated into this file after all global content.
Note: outFile
cannot be used unless module
is None
, System
, or AMD
. This option cannot be used to bundle CommonJS or ES6 modules.
Plugins - plugins
List of language service plugins to run inside the editor.
Language service plugins are a way to provide additional information to a user based on existing TypeScript files. They can enhance existing messages between TypeScript and an editor, or to provide their own error messages.
For example:
- ts-sql-plugin — Adds SQL linting with a template strings SQL builder.
- typescript-styled-plugin — Provides CSS linting inside template strings .
- typescript-eslint-language-service — Provides eslint error messaging and fix-its inside the compiler’s output.
- ts-graphql-plugin — Provides validation and auto-completion inside GraphQL query template strings.
VS Code has the ability for a extension to automatically include language service plugins, and so you may have some running in your editor without needing to define them in your tsconfig.json
.
Remove Comments - removeComments
Strips all comments from TypeScript files when converting into JavaScript. Defaults to false
.
For example, this is a TypeScript file which has a JSDoc comment:
ts
/** The translation of 'Hello world' into Portuguese */export const helloWorldPTBR = "Olá Mundo";
When removeComments
is set to true
:
Try
export const helloWorldPTBR = "Olá Mundo";
Without setting removeComments
or having it as false
:
Try
/** The translation of 'Hello world' into Portuguese */export const helloWorldPTBR = "Olá Mundo";
This means that your comments will show up in the JavaScript code.
Default:
false
Root Dir - rootDir
Default: The longest common path of all non-declaration input files. If composite
is set, the default is instead the directory containing the tsconfig.json
file.
When TypeScript compiles files, it keeps the same directory structure in the output directory as exists in the input directory.
For example, let’s say you have some input files:
MyProj
├── tsconfig.json
├── core
│ ├── a.ts
│ ├── b.ts
│ ├── sub
│ │ ├── c.ts
├── types.d.ts
The inferred value for rootDir
is the longest common path of all non-declaration input files, which in this case is core/
.
If your outDir
was dist
, TypeScript would write this tree:
MyProj
├── dist
│ ├── a.js
│ ├── b.js
│ ├── sub
│ │ ├── c.js
However, you may have intended for core
to be part of the output directory structure. By setting rootDir: "."
in tsconfig.json
, TypeScript would write this tree:
MyProj
├── dist
│ ├── core
│ │ ├── a.js
│ │ ├── b.js
│ │ ├── sub
│ │ │ ├── c.js
Importantly, rootDir
does not affect which files become part of the compilation. It has no interaction with the include
, exclude
, or files
tsconfig.json
settings.
Note that TypeScript will never write an output file to a directory outside of outDir
, and will never skip emitting a file. For this reason, rootDir
also enforces that all files which need to be emitted are underneath the rootDir
path.
For example, let’s say you had this tree:
MyProj
├── tsconfig.json
├── core
│ ├── a.ts
│ ├── b.ts
├── helpers.ts
It would be an error to specify rootDir
as core
and include
as *
because it creates a file (helpers.ts
) that would need to be emitted outside the outDir
(i.e. ../helpers.js
).
Default:
Computed from the list of input files
Released:
Source Map - sourceMap
Enables the generation of sourcemap files. These files allow debuggers and other tools to display the original TypeScript source code when actually working with the emitted JavaScript files. Source map files are emitted as .js.map
(or .jsx.map
) files next to the corresponding .js
output file.
The .js
files will in turn contain a sourcemap comment to indicate to tools where the files are to external tools, for example:
ts
// helloWorld.tsexport declare const helloWorld = "hi";
Compiling with sourceMap
set to true
creates the following JavaScript file:
js
// helloWorld.js"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.helloWorld = "hi";//# sourceMappingURL=// helloWorld.js.map
And this also generates this json map:
json
// helloWorld.js.map{"version": 3,"file": "ex.js","sourceRoot": "","sources": ["../ex.ts"],"names": [],"mappings": ";;AAAa,QAAA,UAAU,GAAG,IAAI,CAAA"}
Default:
false
Target - target
Modern browsers support all ES6 features, so ES6
is a good choice. You might choose to set a lower target if your code is deployed to older environments, or a higher target if your code is guaranteed to run in newer environments.
The target
setting changes which JS features are downleveled and which are left intact. For example, an arrow function () => this
will be turned into an equivalent function
expression if target
is ES5 or lower.
Changing target
also changes the default value of lib
. You may “mix and match” target
and lib
settings as desired, but you could just set target
for convenience.
For developer platforms like Node will have a certain baselines for the their target depending on their version. You can find a set of community organized TSConfigs at tsconfig/bases for common platforms and their versions.
The special ESNext
value refers to the highest version your version of TypeScript supports. This setting should be used with caution, since it doesn’t mean the same thing between different TypeScript versions and can make upgrades less predictable.
Default:
ES3
Allowed:
ES3
(default),ES5
,ES6
/ES2015
(synonymous),ES7
/ES2016
,ES2017
,ES2018
,ES2019
,ES2020
,ESNext
Released:
TS Build Info File - tsBuildInfoFile
This setting lets you specify a file for storing incremental compilation information as a part of composite projects which enables faster building of larger TypeScript codebases. You can read more about composite projects in the handbook.
This option offers a way to configure the place where TypeScript keeps track of the files it stores on the disk to indicate a project’s build state — by default, they are in the same folder as your emitted JavaScript.
Default:
.tsbuildinfo
Related:
Released: