2020-08-28

TypeScript - (tsconfig) Project Options

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

// @filename: card.js
export const defaultCardDeck = "Heart";Try
When imported into a TypeScript file will raise an error:

// @filename: index.ts
import { defaultCardDeck } from "./card";

console.log(defaultCardDeck);Try
Imports fine with allowJs enabled:

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

Default:
false
Related:
checkJs, emitDeclarationOnly
Released:
1.8
# 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:

// parseFloat only takes a string
module.exports.pi = parseFloat(3.124);
When imported into a TypeScript module:

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

// @filename: constants.js
Argument 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
Default:
false
Related:
allowJs, emitDeclarationOnly
# 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.

Default:
true
Related:
incremental, tsBuildInfoFile
Released:
3.0
# 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:

export let helloWorld = "hi";Try
Will generate an index.js file like this:

export let helloWorld = "hi";Try
With a corresponding helloWorld.d.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.

Default:
True when TS
Related:
emitDeclarationOnly
Released:
1.0
# 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:

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

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

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

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

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

export function fn(arr: number[]) {
  const arr2 = [1, ...arr];
}
Turning on downlevelIteration and importHelpers is still false:

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:

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.

Default:
false
Related:
noEmitHelpers, downlevelIteration, importHelpers
# 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
Related:
composite, tsBuildInfoFile
Released:
3.4
# 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:

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

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:

function fn() {}
All 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:

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

"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
Allowed:
react (default),
react-native,
preserve
Released:
2.2
# 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.

Allowed:
See main content
Released:
2.0
# Module - module
Sets the module system for the program. See the Modules chapter of the handbook for more information. You very likely want "CommonJS".

Here’s some example output for this file:

// @filename: index.ts
import { valueOfPi } from "./constants";

export const twoPi = valueOfPi * 2;Try
CommonJS
const constants_1 = require("./constants");
exports.twoPi = constants_1.valueOfPi * 2;Try
UMD
(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
AMD
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
System
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
ESNext
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;Try
ES2020
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;Try
None
"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
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:

$ tsc

example
├── index.js
└── index.ts
With a tsconfig.json like this:

{
  "compilerOptions": {
    "outDir": "dist"
  }
}
Running tsc with these settings moves the files into the specified dist folder:

$ tsc

example
├── dist
│   └── index.js
├── index.ts
└── tsconfig.json
Default:
n/a
Related:
out, outFile
# 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.

Default:
n/a
Related:
out, outDir
Released:
1.0
# 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:

/** The translation of 'Hello world' into Portuguese */
export const helloWorldPTBR = "Olá Mundo";
When removeComments is set to true:

export const helloWorldPTBR = "Olá Mundo";Try
Without setting removeComments or having it as false:

/** 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:

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.ts
│   ├── b.ts
│   ├── sub
│   │   ├── c.ts
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:
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:

// helloWorld.ts
export declare const helloWorld = "hi";
Compiling with sourceMap set to true creates the following JavaScript file:

// helloWorld.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.helloWorld = "hi";
//# sourceMappingURL=// helloWorld.js.map
And this also generates this json map:

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

If you are only working with Node.js, here are recommended targets based on the Node version:

Name Supported Target
Node 8 ES2017
Node 10 ES2018
Node 12 ES2019
These are based on node.green’s database of support.

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:
es5
Allowed:
ES3 (default),
ES5,
ES6/ES2015 (synonomous),
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.

Default:
.tsbuildinfo
Released:
3.4

No comments:

Post a Comment