Intro to the TSConfig Reference

A TSConfig file in a directory indicates that the directory is the root of a TypeScript or JavaScript project. The TSConfig file can be either a tsconfig.json or jsconfig.json, both have the same behavior and the same set of config variables.

This page covers all of the different flags available inside a TSConfig file. It starts with an overview of every flag, then moves into the root attributes in the JSON file, then the compilerOptions which are the bulk of the options and wraps up with watchOptions.


Root Fields

Starting up are the root options in the TSConfig - these options relate to how your TypeScript or JavaScript project is set up.

#File Inclusion

These settings help you ensure that TypeScript picks up the right files.

# Exclude - exclude

Specifies an array of filenames or patterns that should be skipped when resolving include.

Important: exclude only changes which files are included as a result of the include setting. A file specified by exclude can still become part of your codebase due to an import statement in your code, a types inclusion, a /// <reference directive, or being specified in the files list.

It is not a mechanism that prevents a file from being included in the codebase - it simply changes what the include setting finds.

  • Default:

    ["node_modules", "bower_components", "jspm_packages"], plus the value of outDir if one is specified.

  • Related:

    include, files

# Extends - extends

The value of extends is a string which contains a path to another configuration file to inherit from. The path may use Node.js style resolution.

The configuration from the base file are loaded first, then overridden by those in the inheriting config file. All relative paths found in the configuration file will be resolved relative to the configuration file they originated in.

It’s worth noting that files, include and exclude from the inheriting config file overwrite those from the base config file, and that circularity between configuration files is not allowed.

Currently, the only top-level property that is excluded from inheritance is references.

Example

configs/base.json:

json
{ "compilerOptions": { "noImplicitAny": true, "strictNullChecks": true } }

tsconfig.json:

json
{ "extends": "./configs/base", "files": ["main.ts", "supplemental.ts"] }

tsconfig.nostrictnull.json:

json
{ "extends": "./tsconfig", "compilerOptions": { "strictNullChecks": false } }

Properties with relative paths found in the configuration file, which aren’t excluded from inheritance, will be resolved relative to the configuration file they originated in.

  • Default:

    false

  • Released:

    2.1

# Files - files

Specifies an allowlist of files to include in the program. An error occurs if any of the files can’t be found.

json
{ "compilerOptions": {}, "files": [ "core.ts", "sys.ts", "types.ts", "scanner.ts", "parser.ts", "utilities.ts", "binder.ts", "checker.ts", "tsc.ts" ] }

This is useful when you only have a small number of files and don’t need to use a glob to reference many files. If you need that then use include.

# Include - include

Specifies an array of filenames or patterns to include in the program. These filenames are resolved relative to the directory containing the tsconfig.json file.

json
{ "include": ["src/**/*", "tests/**/*"] }

Which would include:

.
├── scripts                ⨯
│   ├── lint.ts            ⨯
│   ├── update_deps.ts     ⨯
│   └── utils.ts           ⨯
├── src                    ✓
│   ├── client             ✓
│   │    ├── index.ts      ✓
│   │    └── utils.ts      ✓
│   ├── server             ✓
│   │    └── index.ts      ✓
├── tests                  ✓
│   ├── app.test.ts        ✓
│   ├── utils.ts           ✓
│   └── tests.d.ts         ✓
├── package.json
├── tsconfig.json
└── yarn.lock

include and exclude support wildcard characters to make glob patterns:

  • * matches zero or more characters (excluding directory separators)
  • ? matches any one character (excluding directory separators)
  • **/ matches any directory nested to any level

If a glob pattern doesn’t include a file extension, then only files with supported extensions are included (e.g. .ts, .tsx, and .d.ts by default, with .js and .jsx if allowJs is set to true).

# References - references

Project references are a way to structure your TypeScript programs into smaller pieces. Using Project References can greatly improve build and editor interaction times, enforce logical separation between components, and organize your code in new and improved ways.

You can read more about how references works in the Project References section of the handbook

  • Default:

    false

# Type Acquisition - typeAcquisition

When you have a JavaScript project in your editor, TypeScript will provide types for your node_modules automatically using the DefinitelyTyped set of @types definitions. This is called automatic type acquisition, and you can customize it using the typeAcquisition object in your configuration.

If you would like to disable or customize this feature, create a jsconfig.json in the root of your project:

json
{ "typeAcquisition": { "enable": false } }

If you have a specific module which should be included (but isn’t in node_modules):

json
{ "typeAcquisition": { "include": ["jest"] } }

If a module should not be automatically acquired, for example if the library is available in your node_modules but your team has agreed to not use it:

json
{ "typeAcquisition": { "exclude": ["jquery"] } }
  • Default:

    false

Compiler Options

These options make up the bulk of TypeScript’s configuration and it covers how the language should work.

#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:

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

When imported into a TypeScript file will raise an error:

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

Imports fine with allowJs enabled:

ts
// @filename: index.ts import { defaultCardDeck } from "./card"; 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:

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

When imported into a TypeScript module:

ts
// @filename: constants.js module.exports.pi = parseFloat(3.124); // @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.

ts
// @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); // @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:

ts
export let helloWorld = "hi";Try

Will generate an index.js file like this:

ts
export let helloWorld = "hi";Try

With a corresponding helloWorld.d.ts:

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

Example: Effects on for / of

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

ts
"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 6 behavior. 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.

ts
"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.

Example: Effects on Array Spreads

This is an array spread:

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:

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

  • Default:

    false

  • Released:

    2.3

# 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:

ts
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 __spread = (this && this.__spread) || function () { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; }; export function fn(arr) { var arr2 = __spread([1], arr); }Try

Then turning on both downlevelIteration and importHelpers:

ts
import { __read, __spread } from "tslib"; export function fn(arr) { var arr2 = __spread([1], 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.

Exports of Non-Value Identifiers

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

ts
import { someType, someFunction } from "someModule"; someFunction(); 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):

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:

ts
function fn() {} All files must be modules when the '--isolatedModules' flag is provided.1208All files must be modules when the '--isolatedModules' flag is provided.Try

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:

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

To this JavaScript:

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

Without knowledge of the values of these members, other transpilers can’t replace the references to Number, 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
  • preserve: Emit .jsx files with the JSX unchanged
  • react-native: Emit .js files with the JSX unchanged
2020 Microsoft
Privacy

Using TypeScript