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:

  1. // @filename: card.js
    export const defaultCardDeck = "Heart";
    Try

When imported into a TypeScript file will raise an error:

  1. // @filename: index.ts
    import { defaultCardDeck } from "./card";
  2. console.log(defaultCardDeck);
    Try

Imports fine with allowJs enabled:

  1. // @filename: index.ts
    import { defaultCardDeck } from "./card";
  2. console.log(defaultCardDeck);
    Try

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.

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:

  1. js
    // parseFloat only takes a string
    module.exports.pi = parseFloat(3.124);

When imported into a TypeScript module:

  1. // @filename: constants.js
    module.exports.pi = parseFloat(3.124);
  2. // @filename: index.ts
    import { pi } from "./constants";
    console.log(pi);
    Try

You will not get any errors. However, if you turn on checkJs then you will get error messages from the JavaScript file.

  1. // @filename: constants.js
    Argument 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);
  2. // @filename: index.ts
    import { pi } from "./constants";
    console.log(pi);
    Try

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 the tsconfig.json file.
  • All implementation files must be matched by an include pattern or listed in the files array. If this constraint is violated, tsc will inform you which files weren’t specified.
  • declaration defaults to true

You can find documentation on TypeScript projects in the handbook.

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:

  1. export let helloWorld = "hi";
    Try

Will generate an index.js file like this:

  1. export let helloWorld = "hi";
    Try

With a corresponding helloWorld.d.ts:

  1. export declare let helloWorld: string;
    Try

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.

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:

    2.9

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.

Project Options - 图1Example: Effects on for / of

With this TypeScript code:

  1. const str = "Hello!";
    for (const s of str) {
    console.log(s);
    }
    Try

Without downlevelIteration enabled, a for / of loop on any object is downleveled to a traditional for loop:

  1. "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);
    }
    Try

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.

  1. "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; }
    }
    Try

You can use tslib via importHelpers to reduce the amount of inline JavaScript too:

  1. "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; }
    }
    Try

Note: enabling downlevelIteration does not improve compliance if Symbol.iterator is not present in the runtime.

Project Options - 图2Example: Effects on Array Spreads

This is an array spread:

  1. js
    // Make a new array who elements are 1 followed by the elements of arr2
    const arr = [1, ...arr2];

Based on the description, it sounds easy to downlevel to ES5:

  1. 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:

  1. js
    // Make an array where the '1' element is missing
    let 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.

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:

  1. ts
    export function fn(arr: number[]) {
    const arr2 = [1, ...arr];
    }

Turning on downlevelIteration and importHelpers is still false:

  1. 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));
    }
    Try

Then turning on both downlevelIteration and importHelpers:

  1. import { __read, __spreadArray } from "tslib";
    export function fn(arr) {
    var arr2 = __spreadArray([1], __read(arr));
    }
    Try

You can use noEmitHelpers when you provide your own implementations of these functions.

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.

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 enums and namespaces. 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.

Project Options - 图3Exports of Non-Value Identifiers

In TypeScript, you can import a type and then subsequently export it:

  1. import { someType, someFunction } from "someModule";
  2. someFunction();
  3. export { someType, someFunction };
    Try

Because there’s no value for someType, the emitted export will not try to export it (this would be a runtime error in JavaScript):

  1. 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.

Project Options - 图4Non-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:

  1. function fn() {}
    '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.
    Try

This restriction doesn’t apply to .d.ts files

Project Options - 图5References 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:

  1. declare const enum Numbers {
    Zero = 0,
    One = 1,
    }
    console.log(Numbers.Zero + Numbers.One);
    Try

To this JavaScript:

  1. "use strict";
    console.log(0 + 1);
    Try

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 equivalent React.createElement calls
  • react-jsx: Emit .js files with the JSX changed to _jsx calls
  • react-jsxdev: Emit .js files with the JSX to _jsx calls
  • preserve: Emit .jsx files with the JSX unchanged
  • react-native: Emit .js files with the JSX unchanged

Project Options - 图6For example

This sample code:

  1. tsx
    export const helloWorld = () => <h1>Hello world</h1>;

Default: "react"

  1. export const helloWorld = () => React.createElement("h1", null, "Hello world");
    Try

Preserve: "preserve"

  1. export const helloWorld = () => <h1>Hello world</h1>;
    Try

React Native: "react-native"

  1. export const helloWorld = () => <h1>Hello world</h1>;
    Try

React 17 transform: "react-jsx"[1]

  1. import { jsx as _jsx } from "react/jsx-runtime";
    export const helloWorld = () => _jsx("h1", { children: "Hello world" }, void 0);
    Try

React 17 dev transform: "react-jsxdev"[1]

  1. 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);
    Try

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

Project Options - 图7High Level libraries

NameContents
ES5Core definitions for all ES3 and ES5 functionality
ES2015Additional APIs available in ES2015 (also known as ES6) - array.find, Promise, Proxy, Symbol, Map, Set, Reflect, etc.
ES6Alias for “ES2015”
ES2016Additional APIs available in ES2016 - array.include, etc.
ES7Alias for “ES2016”
ES2017Additional APIs available in ES2017 - Object.entries, Object.values, Atomics, SharedArrayBuffer, date.formatToParts, typed arrays, etc.
ES2018Additional APIs available in ES2018 - async iterables, promise.finally, Intl.PluralRules, rexexp.groups, etc.
ES2019Additional APIs available in ES2019 - array.flat, array.flatMap, Object.fromEntries, string.trimStart, string.trimEnd, etc.
ES2020Additional APIs available in ES2020 - string.matchAll, etc.
ESNextAdditional APIs available in ESNext - This changes as the JavaScript specification evolves
DOMDOM definitions - window, document, etc.
WebWorkerAPIs available in WebWorker contexts
ScriptHostAPIs for the Windows Script Hosting System

Project Options - 图8Individual 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.

  • Allowed:

    See main content

  • Related:

    noLib

  • Released:

    2.0

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:

  1. // @filename: index.ts
    import { valueOfPi } from "./constants";
  2. export const twoPi = valueOfPi * 2;
    Try

Project Options - 图9CommonJS

  1. "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.twoPi = void 0;
    const constants_1 = require("./constants");
    exports.twoPi = constants_1.valueOfPi * 2;
    Try

Project Options - 图10UMD

  1. (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;
    });
    Try

Project Options - 图11AMD

  1. 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;
    });
    Try

Project Options - 图12System

  1. 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);
    }
    };
    });
    Try

Project Options - 图13ESNext

  1. import { valueOfPi } from "./constants";
    export const twoPi = valueOfPi * 2;
    Try

Project Options - 图14ES2020

  1. import { valueOfPi } from "./constants";
    export const twoPi = valueOfPi * 2;
    Try

Project Options - 图15None

  1. "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.twoPi = void 0;
    const constants_1 = require("./constants");
    exports.twoPi = constants_1.valueOfPi * 2;
    Try
  • Allowed:

    CommonJS (default if target is ES3 or ES5),
    ,
    ES6/ES2015 (synonymous, default for target ES6 and higher),
    ,
    ES2020,
    None,
    UMD,
    AMD,
    System,
    ESNext

  • Related:

    moduleResolution

  • Released:

    1.0

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:

  1. sh
    $ tsc
    example
    ├── index.js
    └── index.ts

With a tsconfig.json like this:

  1. {
    "": "dist"
    }
    }

Running tsc with these settings moves the files into the specified dist folder:

  1. sh
    $ tsc
    example
    ├── 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:

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:

  1. ts
    /** The translation of 'Hello world' into Portuguese */
    export const helloWorldPTBR = "Olá Mundo";

When removeComments is set to true:

  1. export const helloWorldPTBR = "Olá Mundo";
    Try

Without setting removeComments or having it as false:

  1. /** The translation of 'Hello world' into Portuguese */
    export const helloWorldPTBR = "Olá Mundo";
    Try

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:

  1. MyProj
  2. ├── tsconfig.json
  3. ├── core
  4. ├── a.ts
  5. ├── b.ts
  6. ├── sub
  7. ├── c.ts
  8. ├── 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:

  1. MyProj
  2. ├── dist
  3. ├── a.js
  4. ├── b.js
  5. ├── sub
  6. ├── 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:

  1. MyProj
  2. ├── dist
  3. ├── core
  4. ├── a.js
  5. ├── b.js
  6. ├── sub
  7. ├── 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:

  1. MyProj
  2. ├── tsconfig.json
  3. ├── core
  4. ├── a.ts
  5. ├── b.ts
  6. ├── 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:

    1.5

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:

  1. ts
    // helloWorld.ts
    export declare const helloWorld = "hi";

Compiling with sourceMap set to true creates the following JavaScript file:

  1. 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:

  1. 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:

    1.0

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.