Root Fields
Starting up are the root options in the TSConfig - these options relate to how your TypeScript or JavaScript project is set up.
#
Files -
files
Specifies an allowlist of files to include in the program. An error occurs if any of the files can’t be found.
{" ": {}," ": ["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
.
-
Default:
false
-
Related:
-
# 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
, andexclude
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
:{" ": {" ": true," ": true}}tsconfig.json
:{" ": "./configs/base"," ": ["main.ts", "supplemental.ts"]}tsconfig.nostrictnull.json
:{" ": "./tsconfig"," ": {" ": 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:
# 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.lockinclude
andexclude
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 -
Default:
[]
iffiles
is specified;**/*
otherwise. -
Related:
-
Released:
# 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 theinclude
setting. A file specified byexclude
can still become part of your codebase due to animport
statement in your code, atypes
inclusion, a/// <reference
directive, or being specified in thefiles
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
outDir
-
Related:
-
# 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
Compiler Options
These options make up the bulk of TypeScript’s configuration and it covers how the language should work.
- Type Checking
- Modules
- JavaScript Support
- Editor Support
- Interop Constraints
- Backwards Compatibility
- Language and Environment
- Compiler Diagnostics
- Projects
- Output Formatting
- Completeness
- Command Line
- Watch Options
-
undefined
(default) provide suggestions as warnings to editors -
true
unreachable code is ignored -
false
raises compiler errors about unreachable code
# Type Checking
# Allow Unreachable Code -
allowUnreachableCode
When:
These warnings are only about code which is provably unreachable due to the use of JavaScript syntax, for example:
tsfunction fn(n: number) {if (n > 5) {return true;} else {return false;}return true;}With
"allowUnreachableCode": false
:ts
Tryfunctionfn (n : number) {if (n > 5) {return true;} else {return false;}return true;Unreachable code detected.7027Unreachable code detected.}This does not affect errors on the basis of code which appears to be unreachable due to type analysis.
-
Released:
# Allow Unused Labels -
allowUnusedLabels
When:
-
undefined
(default) provide suggestions as warnings to editors -
true
unused labels are ignored -
false
raises compiler errors about unused labels
Labels are very rare in JavaScript and typically indicate an attempt to write an object literal:
ts
TryfunctionverifyAge (age : number) {// Forgot 'return' statementif (age > 18) {verified : true;}}-
Released:
# Always Strict -
alwaysStrict
Ensures that your files are parsed in the ECMAScript strict mode, and emit “use strict” for each source file.
ECMAScript strict mode was introduced in ES5 and provides behavior tweaks to the runtime of the JavaScript engine to improve performance, and makes a set of errors throw instead of silently ignoring them.
- Recommended
-
Default:
true
ifstrict
;false
otherwise. -
Related:
-
Released:
# Exact Optional Property Types -
exactOptionalPropertyTypes
With exactOptionalPropertyTypes enabled, TypeScript applies stricter rules around how it handles properties on
type
orinterfaces
which have a?
prefix.For example, this interface declares that there is a property which can be one of two strings: ‘dark’ or ‘light’ or it should not be in the object.
tsinterface UserDefaults {// The absence of a value represents 'system'colorThemeOverride?: "dark" | "light";}Without this flag enabled, there are three values which you can set
colorThemeOverride
to be: “dark”, “light” andundefined
.Setting the value to
undefined
will allow most JavaScript runtime checks for the existence to fail, which is effectively falsy. However, this isn’t quite accurate;colorThemeOverride: undefined
is not the same ascolorThemeOverride
not being defined. For example,"colorThemeOverride" in settings
would have different behavior withundefined
as the key compared to not being defined.exactOptionalPropertyTypes
makes TypeScript truly enforce the definition provided as an optional property:ts
Tryconstsettings =getUserSettings ();settings .colorThemeOverride = "dark";settings .colorThemeOverride = "light";// But not:Type 'undefined' is not assignable to type '"dark" | "light"' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the type of the target.2412Type 'undefined' is not assignable to type '"dark" | "light"' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the type of the target.settings .colorThemeOverride =undefined ;- Recommended
-
Released:
# No Fallthrough Cases In Switch -
noFallthroughCasesInSwitch
Report errors for fallthrough cases in switch statements. Ensures that any non-empty case inside a switch statement includes either
break
,return
, orthrow
. This means you won’t accidentally ship a case fallthrough bug.ts
Tryconsta : number = 6;switch (a ) {case 0:Fallthrough case in switch.7029Fallthrough case in switch.console .log ("even");case 1:console .log ("odd");break;}-
Released:
# No Implicit Any -
noImplicitAny
In some cases where no type annotations are present, TypeScript will fall back to a type of
any
for a variable when it cannot infer the type.This can cause some errors to be missed, for example:
ts
Tryfunctionfn (s ) {// No error?console .log (s .subtr (3));}fn (42);Turning on
noImplicitAny
however TypeScript will issue an error whenever it would have inferredany
:ts
TryfunctionParameter 's' implicitly has an 'any' type.7006Parameter 's' implicitly has an 'any' type.fn ( ) {s console .log (s .subtr (3));}- Recommended
-
Default:
true
ifstrict
;false
otherwise. -
Related:
-
# No Implicit Override -
noImplicitOverride
When working with classes which use inheritance, it’s possible for a sub-class to get “out of sync” with the functions it overloads when they are renamed in the base class.
For example, imagine you are modeling a music album syncing system:
ts
TryclassAlbum {download () {// Default behavior}}classSharedAlbum extendsAlbum {download () {// Override to get info from many sources}}Then when you add support for machine-learning generated playlists, you refactor the
Album
class to have a ‘setup’ function instead:ts
TryclassAlbum {setup () {// Default behavior}}classMLAlbum extendsAlbum {setup () {// Override to get info from algorithm}}classSharedAlbum extendsAlbum {download () {// Override to get info from many sources}}In this case, TypeScript has provided no warning that
download
onSharedAlbum
expected to override a function in the base class.Using
noImplicitOverride
you can ensure that the sub-classes never go out of sync, by ensuring that functions which override include the keywordoverride
.The following example has
noImplicitOverride
enabled, and you can see the error received whenoverride
is missing:ts
TryclassAlbum {setup () {}}classMLAlbum extendsAlbum {overridesetup () {}}classSharedAlbum extendsAlbum { () {}setup }-
Released:
# No Implicit Returns -
noImplicitReturns
When enabled, TypeScript will check all code paths in a function to ensure they return a value.
ts
TryfunctionFunction lacks ending return statement and return type does not include 'undefined'.2366Function lacks ending return statement and return type does not include 'undefined'.lookupHeadphonesManufacturer (color : "blue" | "black"):string {if (color === "blue") {return "beats";} else {("bose");}}-
Released:
# No Implicit This -
noImplicitThis
Raise error on ‘this’ expressions with an implied ‘any’ type.
For example, the class below returns a function which tries to access
this.width
andthis.height
– but the context forthis
inside the function insidegetAreaFunction
is not the instance of the Rectangle.ts
TryclassRectangle {width : number;height : number;constructor(width : number,height : number) {this.width =width ;this.height =height ;}getAreaFunction () {return function () {return'this' implicitly has type 'any' because it does not have a type annotation.'this' implicitly has type 'any' because it does not have a type annotation.2683this .width *this .height ;
2683'this' implicitly has type 'any' because it does not have a type annotation.'this' implicitly has type 'any' because it does not have a type annotation.};}}- Recommended
-
Default:
true
ifstrict
;false
otherwise. -
Related:
-
Released:
# No Property Access From Index Signature -
noPropertyAccessFromIndexSignature
This setting ensures consistency between accessing a field via the “dot” (
obj.key
) syntax, and “indexed” (obj["key"]
) and the way which the property is declared in the type.Without this flag, TypeScript will allow you to use the dot syntax to access fields which are not defined:
tsinterfaceGameSettings {// Known up-front propertiesspeed : "fast" | "medium" | "slow";quality : "high" | "low";// Assume anything unknown to the interface// is a string.[key : string]: string;}constsettings =getSettings ();settings .speed ;Turning the flag on will raise an error because the unknown field uses dot syntax instead of indexed syntax.
tsconstsettings =getSettings ();settings .speed ;settings .quality ;// This would need to be settings["username"];Property 'username' comes from an index signature, so it must be accessed with ['username'].4111Property 'username' comes from an index signature, so it must be accessed with ['username'].settings . ;username The goal of this flag is to signal intent in your calling syntax about how certain you are this property exists.
-
Released:
# No Unchecked Indexed Access -
noUncheckedIndexedAccess
TypeScript has a way to describe objects which have unknown keys but known values on an object, via index signatures.
tsinterfaceEnvironmentVars {NAME : string;OS : string;// Unknown properties are covered by this index signature.[propName : string]: string;}declare constenv :EnvironmentVars ;// Declared as existingconstsysName =env .NAME ;constos =env .OS ;Turning on
noUncheckedIndexedAccess
will addundefined
to any un-declared field in the type.tsdeclare constenv :EnvironmentVars ;// Declared as existingconstsysName =env .NAME ;constos =env .OS ;-
Released:
# No Unused Locals -
noUnusedLocals
Report errors on unused local variables.
ts
TryconstcreateKeyboard = (modelID : number) => {const'defaultModelID' is declared but its value is never read.6133'defaultModelID' is declared but its value is never read. = 23;defaultModelID return {type : "keyboard",modelID };};-
Released:
# No Unused Parameters -
noUnusedParameters
Report errors on unused parameters in functions.
ts
Tryconst'modelID' is declared but its value is never read.6133'modelID' is declared but its value is never read.createDefaultKeyboard = ( : number) => {modelID constdefaultModelID = 23;return {type : "keyboard",modelID :defaultModelID };};-
Released:
# Strict -
strict
The
strict
flag enables a wide range of type checking behavior that results in stronger guarantees of program correctness. Turning this on is equivalent to enabling all of the strict mode family options, which are outlined below. You can then turn off individual strict mode family checks as needed.Future versions of TypeScript may introduce additional stricter checking under this flag, so upgrades of TypeScript might result in new type errors in your program. When appropriate and possible, a corresponding flag will be added to disable that behavior.
- Recommended
-
Related:
-
Released:
# Strict Bind Call Apply -
strictBindCallApply
When set, TypeScript will check that the built-in methods of functions
call
,bind
, andapply
are invoked with correct argument for the underlying function:ts
Try// With strictBindCallApply onfunctionfn (x : string) {returnparseInt (x );}constn1 =fn .call (undefined , "10");constArgument of type 'boolean' is not assignable to parameter of type 'string'.2345Argument of type 'boolean' is not assignable to parameter of type 'string'.n2 =fn .call (undefined ,false );Otherwise, these functions accept any arguments and will return
any
:ts
Try// With strictBindCallApply offfunctionfn (x : string) {returnparseInt (x );}// Note: No error; return type is 'any'constn =fn .call (undefined , false);- Recommended
-
Default:
true
ifstrict
;false
otherwise. -
Related:
-
Released:
# Strict Function Types -
strictFunctionTypes
When enabled, this flag causes functions parameters to be checked more correctly.
Here’s a basic example with
strictFunctionTypes
off:ts
Tryfunctionfn (x : string) {console .log ("Hello, " +x .toLowerCase ());}typeStringOrNumberFunc = (ns : string | number) => void;// Unsafe assignmentletfunc :StringOrNumberFunc =fn ;// Unsafe call - will crashfunc (10);With
strictFunctionTypes
on , the error is correctly detected:ts
Tryfunctionfn (x : string) {console .log ("Hello, " +x .toLowerCase ());}typeStringOrNumberFunc = (ns : string | number) => void;// Unsafe assignment is preventedletType '(x: string) => void' is not assignable to type 'StringOrNumberFunc'. Types of parameters 'x' and 'ns' are incompatible. Type 'string | number' is not assignable to type 'string'. Type 'number' is not assignable to type 'string'.2322Type '(x: string) => void' is not assignable to type 'StringOrNumberFunc'. Types of parameters 'x' and 'ns' are incompatible. Type 'string | number' is not assignable to type 'string'. Type 'number' is not assignable to type 'string'. :func StringOrNumberFunc =fn ;During development of this feature, we discovered a large number of inherently unsafe class hierarchies, including some in the DOM. Because of this, the setting only applies to functions written in function syntax, not to those in method syntax:
ts
TrytypeMethodish = {func (x : string | number): void;};functionfn (x : string) {console .log ("Hello, " +x .toLowerCase ());}// Ultimately an unsafe assignment, but not detectedconstm :Methodish = {func :fn ,};m .func (10);- Recommended
-
Default:
true
ifstrict
;false
otherwise. -
Related:
-
Released:
# Strict Null Checks -
strictNullChecks
When
strictNullChecks
isfalse
,null
andundefined
are effectively ignored by the language. This can lead to unexpected errors at runtime.When
strictNullChecks
istrue
,null
andundefined
have their own distinct types and you’ll get a type error if you try to use them where a concrete value is expected.For example with this TypeScript code,
users.find
has no guarantee that it will actually find a user, but you can write code as though it will:ts
Trydeclare constloggedInUsername : string;constusers = [{name : "Oby",age : 12 },{name : "Heera",age : 32 },];constloggedInUser =users .find ((u ) =>u .name ===loggedInUsername );console .log (loggedInUser .age );Setting
strictNullChecks
totrue
will raise an error that you have not made a guarantee that theloggedInUser
exists before trying to use it.ts
Trydeclare constloggedInUsername : string;constusers = [{name : "Oby",age : 12 },{name : "Heera",age : 32 },];constloggedInUser =users .find ((u ) =>u .name ===loggedInUsername );'loggedInUser' is possibly 'undefined'.18048'loggedInUser' is possibly 'undefined'.console .log ( .loggedInUser age );The second example failed because the array’s
find
function looks a bit like this simplification:ts// When strictNullChecks: truetype Array = {find(predicate: (value: any, index: number) => boolean): S | undefined;};// When strictNullChecks: false the undefined is removed from the type system,// allowing you to write code which assumes it always found a resulttype Array = {find(predicate: (value: any, index: number) => boolean): S;};- Recommended
-
Default:
true
ifstrict
;false
otherwise. -
Related:
-
Released:
# Strict Property Initialization -
strictPropertyInitialization
When set to true, TypeScript will raise an error when a class property was declared but not set in the constructor.
ts
TryclassUserAccount {name : string;accountType = "user"; : string;email address : string | undefined;constructor(name : string) {this.name =name ;// Note that this.email is not set}}In the above case:
-
this.name
is set specifically. -
this.accountType
is set by default. -
this.email
is not set and raises an error. -
this.address
is declared as potentiallyundefined
which means it does not have to be set. - Recommended
-
Default:
true
ifstrict
;false
otherwise. -
Related:
-
Released:
# Use Unknown In Catch Variables -
useUnknownInCatchVariables
In TypeScript 4.0, support was added to allow changing the type of the variable in a catch clause from
any
tounknown
. Allowing for code like:ts
Trytry {// ...} catch (err : unknown) {// We have to verify err is an// error before using it as one.if (err instanceofError ) {console .log (err .message );}}This pattern ensures that error handling code becomes more comprehensive because you cannot guarantee that the object being thrown is a Error subclass ahead of time. With the flag
useUnknownInCatchVariables
enabled, then you do not need the additional syntax (: unknown
) nor a linter rule to try enforce this behavior.- Recommended
-
Default:
true
ifstrict
;false
otherwise. -
Related:
-
Released:
# Modules
# Allow Arbitrary Extensions -
allowArbitraryExtensions
In TypeScript 5.0, when an import path ends in an extension that isn’t a known JavaScript or TypeScript file extension, the compiler will look for a declaration file for that path in the form of
{file basename}.d.{extension}.ts
. For example, if you are using a CSS loader in a bundler project, you might want to write (or generate) declaration files for those stylesheets:css/* app.css */.cookie-banner {display: none;}ts// app.d.css.tsdeclare const css: {cookieBanner: string;};export default css;ts// App.tsximport styles from "./app.css";styles.cookieBanner; // stringBy default, this import will raise an error to let you know that TypeScript doesn’t understand this file type and your runtime might not support importing it. But if you’ve configured your runtime or bundler to handle it, you can suppress the error with the new
--allowArbitraryExtensions
compiler option.Note that historically, a similar effect has often been achievable by adding a declaration file named
app.css.d.ts
instead ofapp.d.css.ts
- however, this just worked through Node’srequire
resolution rules for CommonJS. Strictly speaking, the former is interpreted as a declaration file for a JavaScript file namedapp.css.js
. Because relative files imports need to include extensions in Node’s ESM support, TypeScript would error on our example in an ESM file under--moduleResolution node16
ornodenext
.For more information, read up the proposal for this feature and its corresponding pull request .
--allowImportingTsExtensions
allows TypeScript files to import each other with a TypeScript-specific extension like.ts
,.mts
, or.tsx
.This flag is only allowed when
--noEmit
or--emitDeclarationOnly
is enabled, since these import paths would not be resolvable at runtime in JavaScript output files. The expectation here is that your resolver (e.g. your bundler, a runtime, or some other tool) is going to make these imports between.ts
files work.When set to true,
allowUmdGlobalAccess
lets you access UMD exports as globals from inside module files. A module file is a file that has imports and/or exports. Without this flag, using an export from a UMD module requires an import declaration.An example use case for this flag would be a web project where you know the particular library (like jQuery or Lodash) will always be available at runtime, but you can’t access it with an import.
-
Released:
# Base URL -
baseUrl
Sets a base directory from which to resolve bare specifier module names. For example, in the directory structure:
project├── ex.ts├── hello│ └── world.ts└── tsconfig.jsonWith
"baseUrl": "./"
, TypeScript will look for files starting at the same folder as thetsconfig.json
:tsimport { helloWorld } from "hello/world";console.log(helloWorld);This resolution has higher priority than lookups from
node_modules
.This feature was designed for use in conjunction with AMD module loaders in the browser, and is not recommended in any other context. As of TypeScript 4.1,
baseUrl
is no longer required to be set when usingpaths
.--customConditions
takes a list of additional conditions that should succeed when TypeScript resolves from anexports
orimports
field of apackage.json
. These conditions are added to whatever existing conditions a resolver will use by default.For example, when this field is set in a
tsconfig.json
as so:jsonc{"compilerOptions": {"target": "es2022","moduleResolution": "bundler","customConditions": ["my-condition"]}}Any time an
exports
orimports
field is referenced inpackage.json
, TypeScript will consider conditions calledmy-condition
.So when importing from a package with the following
package.json
jsonc{// ..."exports": {".": {"my-condition": "./foo.mjs","node": "./bar.mjs","import": "./baz.mjs","require": "./biz.mjs"}}}TypeScript will try to look for files corresponding to
foo.mjs
.This field is only valid under the
node16
,nodenext
, andbundler
options for--moduleResolution
.-
Related:
-
# Module -
module
Sets the module system for the program. See the theory behind TypeScript’s
module
option and its reference page for more information. You very likely want"nodenext"
for modern Node.js projects andpreserve
oresnext
for code that will be bundled.Changing
module
affectsmoduleResolution
which also has a reference page .Here’s some example output for this file:
ts
Try// @filename: index.tsimport {valueOfPi } from "./constants";export consttwoPi =valueOfPi * 2;CommonJS
ts
Try"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.twoPi = void 0;const constants_1 = require("./constants");exports.twoPi = constants_1.valueOfPi * 2;ts
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;});ts
Trydefine(["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
ts
TrySystem.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
ts
Tryimport { valueOfPi } from "./constants";export const twoPi = valueOfPi * 2;ES2015
/ES6
/ES2020
/ES2022
ts
Tryimport { valueOfPi } from "./constants";export const twoPi = valueOfPi * 2;In addition to the base functionality of
ES2015
/ES6
,ES2020
adds support for dynamicimport
s , andimport.meta
whileES2022
further adds support for top levelawait
.node16
/nodenext
Available from 4.7+, the
node16
andnodenext
modes integrate with Node’s native ECMAScript Module support . The emitted JavaScript uses eitherCommonJS
orES2020
output depending on the file extension and the value of thetype
setting in the nearestpackage.json
. Module resolution also works differently. You can learn more in the handbook and Modules Reference .preserve
In
--module preserve
( added in TypeScript 5.4), ECMAScript imports and exports written in input files are preserved in the output, and CommonJS-styleimport x = require("...")
andexport = ...
statements are emitted as CommonJSrequire
andmodule.exports
. In other words, the format of each individual import or export statement is preserved, rather than being coerced into a single format for the whole compilation (or even a whole file).ts
Tryimport { valueOfPi } from "./constants";const constants = require("./constants");export const piSquared = valueOfPi * constants.valueOfPi;While it’s rare to need to mix imports and require calls in the same file, this
module
mode best reflects the capabilities of most modern bundlers, as well as the Bun runtime.Why care about TypeScript’s
module
emit with a bundler or with Bun, where you’re likely also settingnoEmit
? TypeScript’s type checking and module resolution behavior are affected by the module format that it would emit. Settingmodule
gives TypeScript information about how your bundler or runtime will process imports and exports, which ensures that the types you see on imported values accurately reflect what will happen at runtime or after bundling.ts
Try"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.twoPi = void 0;const constants_1 = require("./constants");exports.twoPi = constants_1.valueOfPi * 2;-
Default:
CommonJS
iftarget
isES3
orES5
;ES6
/ES2015
otherwise. -
Allowed:
-
none
-
commonjs
-
system
-
es6
/es2015
-
es2020
-
es2022
-
esnext
-
node16
-
nodenext
-
preserve
-
Related:
-
Released:
# Module Resolution -
moduleResolution
Specify the module resolution strategy:
-
'node16'
or'nodenext'
for modern versions of Node.js. Node.js v12 and later supports both ECMAScript imports and CommonJSrequire
, which resolve using different algorithms. ThesemoduleResolution
values, when combined with the correspondingmodule
values, picks the right algorithm for each resolution based on whether Node.js will see animport
orrequire
in the output JavaScript code. -
'node10'
(previously called'node'
) for Node.js versions older than v10, which only support CommonJSrequire
. You probably won’t need to usenode10
in modern code. -
'bundler'
for use with bundlers. Likenode16
andnodenext
, this mode supports package.json"imports"
and"exports"
, but unlike the Node.js resolution modes,bundler
never requires file extensions on relative paths in imports. -
'classic'
was used in TypeScript before the release of 1.6.classic
should not be used. -
Default:
Classic
ifmodule
isAMD
,UMD
,System
, orES6
/ES2015
; Matches ifmodule
isnode16
ornodenext
;Node
otherwise. -
Allowed:
-
classic
-
node10
/node
-
node16
-
nodenext
-
bundler
-
Related:
-
# Module Suffixes -
moduleSuffixes
Provides a way to override the default list of file name suffixes to search when resolving a module.
{" ": {" ": [".ios", ".native", ""]}}Given the above configuration, an import like the following:
tsimport * as foo from "./foo";TypeScript will look for the relative files
./foo.ios.ts
,./foo.native.ts
, and finally./foo.ts
.Note the empty string
""
inmoduleSuffixes
which is necessary for TypeScript to also look-up./foo.ts
.This feature can be useful for React Native projects where each target platform can use a separate tsconfig.json with differing
moduleSuffixes
.-
Released:
# No Resolve -
noResolve
By default, TypeScript will examine the initial set of files for
import
and<reference
directives and add these resolved files to your program.If
noResolve
is set, this process doesn’t happen. However,import
statements are still checked to see if they resolve to a valid module, so you’ll need to make sure this is satisfied by some other means.A series of entries which re-map imports to lookup locations relative to the
baseUrl
if set, or to the tsconfig file itself otherwise. There is a larger coverage ofpaths
in themoduleResolution
reference page .paths
lets you declare how TypeScript should resolve an import in yourrequire
/import
s.{" ": {" ": {"jquery": ["./vendor/jquery/dist/jquery"]}}}This would allow you to be able to write
import "jquery"
, and get all of the correct typing locally.{" ": {" ": {"app/*": ["./src/app/*"],"config/*": ["./src/app/_config/*"],"environment/*": ["./src/environments/*"],"shared/*": ["./src/app/_shared/*"],"helpers/*": ["./src/helpers/*"],"tests/*": ["./src/tests/*"]},}In this case, you can tell the TypeScript file resolver to support a number of custom prefixes to find code.
Note that this feature does not change how import paths are emitted by
tsc
, sopaths
should only be used to inform TypeScript that another tool has this mapping and will use it at runtime or when bundling.Allows importing modules with a
.json
extension, which is a common practice in node projects. This includes generating a type for theimport
based on the static JSON shape.TypeScript does not support resolving JSON files by default:
ts
Try// @filename: settings.json{"repo": "TypeScript","dry": false,"debug": false}// @filename: index.tsimportCannot find module './settings.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.2732Cannot find module './settings.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.settings from"./settings.json" ;settings .debug === true;settings .dry === 2;Enabling the option allows importing JSON, and validating the types in that JSON file.
ts
Try// @filename: settings.json{"repo": "TypeScript","dry": false,"debug": false}// @filename: index.tsimportsettings from "./settings.json";settings .debug === true;This comparison appears to be unintentional because the types 'boolean' and 'number' have no overlap.2367This comparison appears to be unintentional because the types 'boolean' and 'number' have no overlap.settings .dry === 2;--resolvePackageJsonExports
forces TypeScript to consult theexports
field ofpackage.json
files if it ever reads from a package innode_modules
.This option defaults to
true
under thenode16
,nodenext
, andbundler
options for--moduleResolution
.-
Default:
true
whenmoduleResolution
isnode16
,nodenext
, orbundler
; otherwisefalse
-
Related:
-
# Resolve package.json Imports -
resolvePackageJsonImports
--resolvePackageJsonImports
forces TypeScript to consult theimports
field ofpackage.json
files when performing a lookup that starts with#
from a file whose ancestor directory contains apackage.json
.This option defaults to
true
under thenode16
,nodenext
, andbundler
options for--moduleResolution
.-
Default:
true
whenmoduleResolution
isnode16
,nodenext
, orbundler
; otherwisefalse
-
Related:
-
# 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 thetsconfig.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.tsThe inferred value for
rootDir
is the longest common path of all non-declaration input files, which in this case iscore/
.If your
outDir
wasdist
, TypeScript would write this tree:MyProj├── dist│ ├── a.js│ ├── b.js│ ├── sub│ │ ├── c.jsHowever, you may have intended for
core
to be part of the output directory structure. By settingrootDir: "."
intsconfig.json
, TypeScript would write this tree:MyProj├── dist│ ├── core│ │ ├── a.js│ │ ├── b.js│ │ ├── sub│ │ │ ├── c.jsImportantly,
rootDir
does not affect which files become part of the compilation . It has no interaction with theinclude
,exclude
, orfiles
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 therootDir
path.For example, let’s say you had this tree:
MyProj├── tsconfig.json├── core│ ├── a.ts│ ├── b.ts├── helpers.tsIt would be an error to specify
rootDir
ascore
andinclude
as*
because it creates a file (helpers.ts
) that would need to be emitted outside theoutDir
(i.e.../helpers.js
).-
Default:
Computed from the list of input files.
-
Released:
# Root Dirs -
rootDirs
Using
rootDirs
, you can inform the compiler that there are many “virtual” directories acting as a single root. This allows the compiler to resolve relative module imports within these “virtual” directories, as if they were merged in to one directory.For example:
src└── views└── view1.ts (can import "./template1", "./view2`)└── view2.ts (can import "./template1", "./view1`)generated└── templates└── views└── template1.ts (can import "./view1", "./view2"){" ": {" ": ["src/views", "generated/templates/views"]}}This does not affect how TypeScript emits JavaScript, it only emulates the assumption that they will be able to work via those relative paths at runtime.
rootDirs
can be used to provide a separate “type layer” to files that are not TypeScript or JavaScript by providing a home for generated.d.ts
files in another folder. This technique is useful for bundled applications where you useimport
of files that aren’t necessarily code:shsrc└── index.ts└── css└── main.css└── navigation.cssgenerated└── css└── main.css.d.ts└── navigation.css.d.ts{" ": {" ": ["src", "generated"]}}This technique lets you generate types ahead of time for the non-code source files. Imports then work naturally based off the source file’s location. For example
./src/index.ts
can import the file./src/css/main.css
and TypeScript will be aware of the bundler’s behavior for that filetype via the corresponding generated declaration file.ts
Try// @filename: index.tsimport {appClass } from "./main.css";-
Default:
Computed from the list of input files.
-
Released:
# Type Roots -
typeRoots
By default all visible ”
@types
” packages are included in your compilation. Packages innode_modules/@types
of any enclosing folder are considered visible . For example, that means packages within./node_modules/@types/
,../node_modules/@types/
,../../node_modules/@types/
, and so on.If
typeRoots
is specified, only packages undertypeRoots
will be included. For example:{" ": {" ": ["./typings", "./vendor/types"]}}This config file will include all packages under
./typings
and./vendor/types
, and no packages from./node_modules/@types
. All paths are relative to thetsconfig.json
.-
Related:
-
# Types -
types
By default all visible ”
@types
” packages are included in your compilation. Packages innode_modules/@types
of any enclosing folder are considered visible . For example, that means packages within./node_modules/@types/
,../node_modules/@types/
,../../node_modules/@types/
, and so on.If
types
is specified, only packages listed will be included in the global scope. For instance:{" ": {" ": ["node", "jest", "express"]}}This
tsconfig.json
file will only include./node_modules/@types/node
,./node_modules/@types/jest
and./node_modules/@types/express
. Other packages undernode_modules/@types/*
will not be included.What does this affect?
This option does not affect how
@types/*
are included in your application code, for example if you had the abovecompilerOptions
example with code like:tsimport * as moment from "moment";moment().format("MMMM Do YYYY, h:mm:ss a");The
moment
import would be fully typed.When you have this option set, by not including a module in the
types
array it: -
Will not add globals to your project (e.g
process
in node, orexpect
in Jest) - Will not have exports appear as auto-import recommendations
-
Related:
-
# Emit
# 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 totrue
, running the compiler with this TypeScript code:ts
Tryexport lethelloWorld = "hi";Will generate an
index.js
file like this:ts
Tryexport let helloWorld = "hi";With a corresponding
helloWorld.d.ts
:ts
Tryexport declare let helloWorld: string;When working with
.d.ts
files for JavaScript files you may want to useemitDeclarationOnly
or useoutDir
to ensure that the JavaScript files are not overwritten.-
Default:
true
ifcomposite
;false
otherwise. -
Related:
-
Released:
# Declaration Dir -
declarationDir
Offers a way to configure the root directory for where declaration files are emitted.
example├── index.ts├── package.json└── tsconfig.jsonwith this
tsconfig.json
:{" ": {" ": true," ": "./types"}}Would place the d.ts for the
index.ts
in atypes
folder:example├── index.js├── index.ts├── package.json├── tsconfig.json└── types└── index.d.ts-
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.
-
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)
), andSymbol.iterator
.downlevelIteration
allows for these iteration primitives to be used more accurately in ES5 environments if aSymbol.iterator
implementation is present.Example: Effects on
for / of
With this TypeScript code:
ts
Tryconststr = "Hello!";for (consts ofstr ) {console .log (s );}Without
downlevelIteration
enabled, afor / of
loop on any object is downleveled to a traditionalfor
loop:ts
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 afor-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 aSymbol.iterator
implementation (either native or polyfill). If this implementation is missing, you’ll fall back to index-based iteration.ts
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:ts
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 ifSymbol.iterator
is not present in the runtime.Example: Effects on Array Spreads
This is an array spread:
js// Make a new array whose 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 a source array is missing one or more items (contains a hole), the spread syntax will replace each empty item with
undefined
, whereas.concat
will leave them intact.js// Make an array where the element at index 1 is missinglet arrayWithHole = ["a", , "c"];let spread = [...arrayWithHole];let concatenated = [].concat(arrayWithHole);console.log(arrayWithHole);// [ 'a', <1 empty item>, 'c' ]console.log(spread);// [ 'a', undefined, 'c' ]console.log(concatenated);// [ 'a', <1 empty item>, 'c' ]Just as with
for / of
,downlevelIteration
will useSymbol.iterator
(if present) to more accurately emulate ES 6 behavior.-
Related:
-
Released:
# Emit BOM -
emitBOM
Controls whether TypeScript will emit a byte order mark (BOM) when writing output files. Some runtime environments require a BOM to correctly interpret a JavaScript files; others require that it is not present. The default value of
false
is generally best unless you have a reason to change it.This setting is useful in two cases:
- You are using a transpiler other than TypeScript to generate your JavaScript.
-
You are using TypeScript to only generate
d.ts
files for your consumers. -
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 thetslib
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:
tsexport function fn(arr: number[]) {const arr2 = [1, ...arr];}Turning on
downlevelIteration
andimportHelpers
is still false:ts
Tryvar __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, pack) {if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {if (ar || !(i in from)) {if (!ar) ar = Array.prototype.slice.call(from, 0, i);ar[i] = from[i];}}return to.concat(ar || Array.prototype.slice.call(from));};export function fn(arr) {var arr2 = __spreadArray([1], __read(arr), false);}Then turning on both
downlevelIteration
andimportHelpers
:ts
Tryimport { __read, __spreadArray } from "tslib";export function fn(arr) {var arr2 = __spreadArray([1 ], __read(arr), false);}You can use
noEmitHelpers
when you provide your own implementations of these functions.-
Related:
-
# Imports Not Used As Values -
importsNotUsedAsValues
Deprecated in favor of
verbatimModuleSyntax
.This flag controls how
import
works, there are 3 different options:remove
: The default behavior of droppingimport
statements which only reference types.preserve
: Preserves allimport
statements whose values or types are never used. This can cause imports/side-effects to be preserved.error
: This preserves all imports (the same as the preserve option), but will error when a value import is only used as a type. This might be useful if you want to ensure no values are being accidentally imported, but still make side-effect imports explicit.This flag works because you can use
import type
to explicitly create animport
statement which should never be emitted into JavaScript.-
Default:
remove
-
Allowed:
-
remove
-
preserve
-
error
-
Related:
-
Released:
# Inline Source Map -
inlineSourceMap
When set, instead of writing out a
.js.map
file to provide source maps, TypeScript will embed the source map content in the.js
files. Although this results in larger JS files, it can be convenient in some scenarios. For example, you might want to debug JS files on a webserver that doesn’t allow.map
files to be served.Mutually exclusive with
sourceMap
.For example, with this TypeScript:
tsconst helloWorld = "hi";console.log(helloWorld);Converts to this JavaScript:
ts
Try"use strict";const helloWorld = "hi";console.log(helloWorld);Then enable building it with
inlineSourceMap
enabled there is a comment at the bottom of the file which includes a source-map for the file.ts
Try"use strict";const helloWorld = "hi";console.log(helloWorld);//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMifQ==-
Released:
# Inline Sources -
inlineSources
When set, TypeScript will include the original content of the
.ts
file as an embedded string in the source map (using the source map’ssourcesContent
property). This is often useful in the same cases asinlineSourceMap
.Requires either
sourceMap
orinlineSourceMap
to be set.For example, with this TypeScript:
ts
TryconsthelloWorld = "hi";console .log (helloWorld );By default converts to this JavaScript:
ts
Try"use strict";const helloWorld = "hi";console.log(helloWorld);Then enable building it with
inlineSources
andinlineSourceMap
enabled there is a comment at the bottom of the file which includes a source-map for the file. Note that the end is different from the example ininlineSourceMap
because the source-map now contains the original source code also.ts
Try"use strict";const helloWorld = "hi";console.log(helloWorld);//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBoZWxsb1dvcmxkID0gXCJoaVwiO1xuY29uc29sZS5sb2coaGVsbG9Xb3JsZCk7Il19-
Released:
# Map Root -
mapRoot
Specify the location where debugger should locate map files instead of generated locations. This string is treated verbatim inside the source-map, for example:
{" ": {" ": true," ": "https://my-website.com/debug/sourcemaps/"}}Would declare that
index.js
will have sourcemaps athttps://my-website.com/debug/sourcemaps/index.js.map
.Specify the end of line sequence to be used when emitting files: ‘CRLF’ (dos) or ‘LF’ (unix).
-
Default:
lf
-
Allowed:
-
crlf
-
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.
Instead of importing helpers with
importHelpers
, you can provide implementations in the global scope for the helpers you use and completely turn off emitting of helper functions.For example, using this
async
function in ES5 requires aawait
-like function andgenerator
-like function to run:ts
TryconstgetAPI = async (url : string) => {// Get APIreturn {};};Which creates quite a lot of JavaScript:
ts
Try"use strict";var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }return new (P || (P = Promise))(function (resolve, reject) {function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }step((generator = generator.apply(thisArg, _arguments || [])).next());});};var __generator = (this && this.__generator) || function (thisArg, body) {var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;function verb(n) { return function (v) { return step([n, v]); }; }function step(op) {if (f) throw new TypeError("Generator is already executing.");while (g && (g = 0, op[0] && (_ = 0)), _) try {if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;if (y = 0, t) op = [ op[0] & 2, t.value];switch (op[0]) {case 0: case 1: t = op; break;case 4: _.label++; return { value: op[1], done: false };case 5: _.label++; y = op[1]; op = [0]; continue;case 7: op = _.ops.pop(); _.trys.pop(); continue;default:if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }if (t[2]) _.ops.pop();_.trys.pop(); continue;}op = body.call(thisArg, _);} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };}};var getAPI = function (url) { return __awaiter(void 0, void 0, void 0, function () {return __generator(this, function (_a) {// Get APIreturn [2 /*return*/, {}];});}); };Which can be switched out with your own globals via this flag:
ts
Try"use strict";var getAPI = function (url) { return __awaiter(void 0, void 0, void 0, function () {return __generator(this, function (_a) {// Get APIreturn [2 /*return*/, {}];});}); };-
Related:
-
Released:
# No Emit On Error -
noEmitOnError
Do not emit compiler output files like JavaScript source code, source-maps or declarations if any errors were reported.
This defaults to
false
, making it easier to work with TypeScript in a watch-like environment where you may want to see results of changes to your code in another environment before making sure all errors are resolved.-
Released:
# 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; seerootDir
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.tsWith a
tsconfig.json
like this:{" ": {" ": "dist"}}Running
tsc
with these settings moves the files into the specifieddist
folder:sh$ tscexample├── dist│ └── index.js├── index.ts└── tsconfig.json-
Related:
-
# Out File -
outFile
If specified, all global (non-module) files will be concatenated into the single output file specified.
If
module
issystem
oramd
, all module files will also be concatenated into this file after all global content.Note:
outFile
cannot be used unlessmodule
isNone
,System
, orAMD
. This option cannot be used to bundle CommonJS or ES6 modules.-
Related:
-
Released:
# Preserve Const Enums -
preserveConstEnums
Do not erase
const enum
declarations in generated code.const enum
s provide a way to reduce the overall memory footprint of your application at runtime by emitting the enum value instead of a reference.For example with this TypeScript:
ts
Tryconst enumAlbum {JimmyEatWorldFutures = 1,TubRingZooHypothesis = 2,DogFashionDiscoAdultery = 3,}constselectedAlbum =Album .JimmyEatWorldFutures ;if (selectedAlbum ===Album .JimmyEatWorldFutures ) {console .log ("That is a great choice.");}The default
const enum
behavior is to convert anyAlbum.Something
to the corresponding number literal, and to remove a reference to the enum from the JavaScript completely.ts
Try"use strict";const selectedAlbum = 1 /* Album.JimmyEatWorldFutures */;if (selectedAlbum === 1 /* Album.JimmyEatWorldFutures */) {console.log("That is a great choice.");}With
preserveConstEnums
set totrue
, theenum
exists at runtime and the numbers are still emitted.ts
Try"use strict";var Album;(function (Album) {Album[Album["JimmyEatWorldFutures"] = 1] = "JimmyEatWorldFutures";Album[Album["TubRingZooHypothesis"] = 2] = "TubRingZooHypothesis";Album[Album["DogFashionDiscoAdultery"] = 3] = "DogFashionDiscoAdultery";})(Album || (Album = {}));const selectedAlbum = 1 /* Album.JimmyEatWorldFutures */;if (selectedAlbum === 1 /* Album.JimmyEatWorldFutures */) {console.log("That is a great choice.");}This essentially makes such
const enums
a source-code feature only, with no runtime traces.-
Default:
true
ifisolatedModules
;false
otherwise.# Preserve Value Imports -
preserveValueImports
Deprecated in favor of
verbatimModuleSyntax
.There are some cases where TypeScript can’t detect that you’re using an import. For example, take the following code:
tsimport { Animal } from "./animal.js";eval("console.log(new Animal().isDangerous())");or code using ‘Compiles to HTML’ languages like Svelte or Vue.
preserveValueImports
will prevent TypeScript from removing the import, even if it appears unused.When combined with
isolatedModules
: imported types must be marked as type-only because compilers that process single files at a time have no way of knowing whether imports are values that appear unused, or a type that must be removed in order to avoid a runtime crash.-
Related:
-
Released:
# 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 totrue
:ts
Tryexport const helloWorldPTBR = "Olá Mundo";Without setting
removeComments
or having it asfalse
:ts
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.
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 where the files are to external tools, for example:ts// helloWorld.tsexport declare const helloWorld = "hi";Compiling with
sourceMap
set totrue
creates the following JavaScript file:js// helloWorld.js"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.helloWorld = "hi";//# sourceMappingURL=// helloWorld.js.mapAnd 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"}Specify the location where a debugger should locate TypeScript files instead of relative source locations. This string is treated verbatim inside the source-map where you can use a path or a URL:
{" ": {" ": true," ": "https://my-website.com/debug/source/"}}Would declare that
index.js
will have a source file athttps://my-website.com/debug/source/index.ts
.Do not emit declarations for code that has an
@internal
annotation in its JSDoc comment. This is an internal compiler option; use at your own risk, because the compiler does not check that the result is valid. If you are searching for a tool to handle additional levels of visibility within yourd.ts
files, look at api-extractor .ts
Try/*** Days available in a week* @internal*/export constdaysInAWeek = 7;/** Calculate how much someone earns in a week */export functionweeklySalary (dayRate : number) {returndaysInAWeek *dayRate ;}With the flag set to
false
(default):ts
Try/*** Days available in a week* @internal*/export declare const daysInAWeek = 7;/** Calculate how much someone earns in a week */export declare function weeklySalary(dayRate: number): number;With
stripInternal
set totrue
thed.ts
emitted will be redacted.ts
Try/** Calculate how much someone earns in a week */export declare function weeklySalary(dayRate: number): number;The JavaScript output is still the same.
-
Internal
# JavaScript Support
# 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
Try// @filename: card.jsexport constdefaultCardDeck = "Heart";When imported into a TypeScript file will raise an error:
ts
Try// @filename: index.tsimport {defaultCardDeck } from "./card";console .log (defaultCardDeck );Imports fine with
allowJs
enabled:ts
Try// @filename: index.tsimport {defaultCardDeck } from "./card";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.It can also be used along-side
declaration
andemitDeclarationOnly
to create declarations for JS files .-
Related:
-
Released:
# Check JS -
checkJs
Works in tandem with
allowJs
. WhencheckJs
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.142);When imported into a TypeScript module:
ts
Try// @filename: constants.jsmodule .exports .pi =parseFloat (3.142);// @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.ts
Try// @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.142 );// @filename: index.tsimport {pi } from "./constants";console .log (pi );-
Related:
-
Released:
# Max Node Module JS Depth -
maxNodeModuleJsDepth
The maximum dependency depth to search under
node_modules
and load JavaScript files.This flag can only be used when
allowJs
is enabled, and is used if you want to have TypeScript infer types for all of the JavaScript inside yournode_modules
.Ideally this should stay at 0 (the default), and
d.ts
files should be used to explicitly define the shape of modules. However, there are cases where you may want to turn this on at the expense of speed and potential accuracy.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
.When set to true,
allowSyntheticDefaultImports
allows you to write an import like:tsimport React from "react";instead of:
tsimport * as React from "react";When the module does not explicitly specify a default export.
For example, without
allowSyntheticDefaultImports
as true:ts
Try// @filename: utilFunctions.jsconstgetStringLength = (str ) =>str .length ;module .exports = {getStringLength ,};// @filename: index.tsimportModule '"/home/runner/work/TypeScript-Website/TypeScript-Website/packages/typescriptlang-org/utilFunctions"' has no default export.1192Module '"/home/runner/work/TypeScript-Website/TypeScript-Website/packages/typescriptlang-org/utilFunctions"' has no default export. from "./utilFunctions";utils constcount =utils .getStringLength ("Check JS");This code raises an error because there isn’t a
default
object which you can import. Even though it feels like it should. For convenience, transpilers like Babel will automatically create a default if one isn’t created. Making the module look a bit more like:js// @filename: utilFunctions.jsconst getStringLength = (str) => str.length;const allFunctions = {getStringLength,};module.exports = allFunctions;module.exports.default = allFunctions;This flag does not affect the JavaScript emitted by TypeScript, it’s only for the type checking. This option brings the behavior of TypeScript in-line with Babel, where extra code is emitted to make using a default export of a module more ergonomic.
-
Default:
true
ifesModuleInterop
is enabled,module
issystem
, ormoduleResolution
isbundler
;false
otherwise. -
Related:
-
Released:
# ES Module Interop -
esModuleInterop
By default (with
esModuleInterop
false or not set) TypeScript treats CommonJS/AMD/UMD modules similar to ES6 modules. In doing this, there are two parts in particular which turned out to be flawed assumptions:a namespace import like
import * as moment from "moment"
acts the same asconst moment = require("moment")
a default import like
import moment from "moment"
acts the same asconst moment = require("moment").default
This mis-match causes these two issues:
the ES6 modules spec states that a namespace import (
import * as x
) can only be an object, by having TypeScript treating it the same as= require("x")
then TypeScript allowed for the import to be treated as a function and be callable. That’s not valid according to the spec.while accurate to the ES6 modules spec, most libraries with CommonJS/AMD/UMD modules didn’t conform as strictly as TypeScript’s implementation.
Turning on
esModuleInterop
will fix both of these problems in the code transpiled by TypeScript. The first changes the behavior in the compiler, the second is fixed by two new helper functions which provide a shim to ensure compatibility in the emitted JavaScript:tsimport * as fs from "fs";import _ from "lodash";fs.readFileSync("file.txt", "utf8");_.chunk(["a", "b", "c", "d"], 2);With
esModuleInterop
disabled:ts
Try"use strict";Object.defineProperty(exports, "__esModule", { value: true });const fs = require("fs");const lodash_1 = require("lodash");fs.readFileSync("file.txt", "utf8");lodash_1.default.chunk(["a", "b", "c", "d"], 2);With
esModuleInterop
set totrue
:ts
Try"use strict";var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {if (k2 === undefined) k2 = k;var desc = Object.getOwnPropertyDescriptor(m, k);if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {desc = { enumerable: true, get: function() { return m[k]; } };}Object.defineProperty(o, k2, desc);}) : (function(o, m, k, k2) {if (k2 === undefined) k2 = k;o[k2] = m[k];}));var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {Object.defineProperty(o, "default", { enumerable: true, value: v });}) : function(o, v) {o["default"] = v;});var __importStar = (this && this.__importStar) || function (mod) {if (mod && mod.__esModule) return mod;var result = {};if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);__setModuleDefault(result, mod);return result;};var __importDefault = (this && this.__importDefault) || function (mod) {return (mod && mod.__esModule) ? mod : { "default": mod };};Object.defineProperty(exports, "__esModule", { value: true });const fs = __importStar(require("fs"));const lodash_1 = __importDefault(require("lodash"));fs.readFileSync("file.txt", "utf8");lodash_1.default.chunk(["a", "b", "c", "d"], 2);Note : The namespace import
import * as fs from "fs"
only accounts for properties which are owned (basically properties set on the object and not via the prototype chain) on the imported object. If the module you’re importing defines its API using inherited properties, you need to use the default import form (import fs from "fs"
), or disableesModuleInterop
.Note : You can make JS emit terser by enabling
importHelpers
:ts
Try"use strict";Object.defineProperty(exports, "__esModule", { value: true });const tslib_1 = require("tslib");const fs = tslib_1.__importStar(require("fs"));const lodash_1 = tslib_1.__importDefault(require("lodash"));fs.readFileSync("file.txt", "utf8");lodash_1.default.chunk(["a", "b", "c", "d"], 2);Enabling
esModuleInterop
will also enableallowSyntheticDefaultImports
.- Recommended
-
Default:
true
ifmodule
isnode16
ornodenext
;false
otherwise. -
Related:
-
Released:
# Force Consistent Casing In File Names -
forceConsistentCasingInFileNames
TypeScript follows the case sensitivity rules of the file system it’s running on. This can be problematic if some developers are working in a case-sensitive file system and others aren’t. If a file attempts to import
fileManager.ts
by specifying./FileManager.ts
the file will be found in a case-insensitive file system, but not on a case-sensitive file system.When this option is set, TypeScript will issue an error if a program tries to include a file by a casing different from the casing on disk.
- Recommended
-
Default:
true
# 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 andnamespace
s. Setting theisolatedModules
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
Tryimport {someType ,someFunction } from "someModule";someFunction ();export {someType ,someFunction };Because there’s no value for
someType
, the emittedexport
will not try to export it (this would be a runtime error in JavaScript):jsexport { 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, namespaces are only allowed in modules (which means it has some form ofimport
/export
). An error occurs if a namespace is found in a non-module file:ts
TrynamespaceNamespaces are not allowed in global script files when 'isolatedModules' is enabled. If this file is not intended to be a global script, set 'moduleDetection' to 'force' or add an empty 'export {}' statement.1280Namespaces are not allowed in global script files when 'isolatedModules' is enabled. If this file is not intended to be a global script, set 'moduleDetection' to 'force' or add an empty 'export {}' statement. {Instantiated export constx = 1;}This restriction doesn’t apply to
.d.ts
files.References to
const enum
membersIn TypeScript, when you reference a
const enum
member, the reference is replaced by its actual value in the emitted JavaScript. Changing this TypeScript:ts
Trydeclare const enumNumbers {Zero = 0,One = 1,}console .log (Numbers .Zero +Numbers .One );To this JavaScript:
ts
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 noNumbers
object at runtime). Because of this, whenisolatedModules
is set, it is an error to reference an ambientconst enum
member.This is to reflect the same flag in Node.js; which does not resolve the real path of symlinks.
This flag also exhibits the opposite behavior to Webpack’s
resolve.symlinks
option (i.e. setting TypeScript’spreserveSymlinks
to true parallels setting Webpack’sresolve.symlinks
to false, and vice-versa).With this enabled, references to modules and packages (e.g.
import
s and/// <reference type="..." />
directives) are all resolved relative to the location of the symbolic link file, rather than relative to the path that the symbolic link resolves to.By default, TypeScript does something called import elision . Basically, if you write something like
tsimport { Car } from "./car";export function drive(car: Car) {// ...}TypeScript detects that you’re only using an import for types and drops the import entirely. Your output JavaScript might look something like this:
jsexport function drive(car) {// ...}Most of the time this is good, because if
Car
isn’t a value that’s exported from./car
, we’ll get a runtime error.But it does add a layer of complexity for certain edge cases. For example, notice there’s no statement like
import "./car";
- the import was dropped entirely. That actually makes a difference for modules that have side-effects or not.TypeScript’s emit strategy for JavaScript also has another few layers of complexity - import elision isn’t always just driven by how an import is used - it often consults how a value is declared as well. So it’s not always clear whether code like the following
tsexport { Car } from "./car";should be preserved or dropped. If
Car
is declared with something like aclass
, then it can be preserved in the resulting JavaScript file. But ifCar
is only declared as atype
alias orinterface
, then the JavaScript file shouldn’t exportCar
at all.While TypeScript might be able to make these emit decisions based on information from across files, not every compiler can.
The
type
modifier on imports and exports helps with these situations a bit. We can make it explicit whether an import or export is only being used for type analysis, and can be dropped entirely in JavaScript files by using thetype
modifier.ts// This statement can be dropped entirely in JS outputimport type * as car from "./car";// The named import/export 'Car' can be dropped in JS outputimport { type Car } from "./car";export { type Car } from "./car";type
modifiers are not quite useful on their own - by default, module elision will still drop imports, and nothing forces you to make the distinction betweentype
and plain imports and exports. So TypeScript has the flag--importsNotUsedAsValues
to make sure you use thetype
modifier,--preserveValueImports
to prevent some module elision behavior, and--isolatedModules
to make sure that your TypeScript code works across different compilers. Unfortunately, understanding the fine details of those 3 flags is hard, and there are still some edge cases with unexpected behavior.TypeScript 5.0 introduces a new option called
--verbatimModuleSyntax
to simplify the situation. The rules are much simpler - any imports or exports without atype
modifier are left around. Anything that uses thetype
modifier is dropped entirely.ts// Erased away entirely.import type { A } from "a";// Rewritten to 'import { b } from "bcd";'import { b, type c, type d } from "bcd";// Rewritten to 'import {} from "xyz";'import { type xyz } from "xyz";With this new option, what you see is what you get.
That does have some implications when it comes to module interop though. Under this flag, ECMAScript
Input TypeScript Output JavaScriptimport
s andexport
s won’t be rewritten torequire
calls when your settings or file extension implied a different module system. Instead, you’ll get an error. If you need to emit code that usesrequire
andmodule.exports
, you’ll have to use TypeScript’s module syntax that predates ES2015:tsfunction foo() {}function bar() {}function baz() {}export = {foo,bar,baz,};jsfunction foo() {}function bar() {}function baz() {}module.exports = {foo,bar,baz,};While this is a limitation, it does help make some issues more obvious. For example, it’s very common to forget to set the
type
field inpackage.json
under--module node16
. As a result, developers would start writing CommonJS modules instead of an ES modules without realizing it, giving surprising lookup rules and JavaScript output. This new flag ensures that you’re intentional about the file type you’re using because the syntax is intentionally different.Because
--verbatimModuleSyntax
provides a more consistent story than--importsNotUsedAsValues
and--preserveValueImports
, those two existing flags are being deprecated in its favor.For more details, read up on the original pull request and its proposal issue .
In prior versions of TypeScript, this controlled what encoding was used when reading text files from disk. Today, TypeScript assumes UTF-8 encoding, but will correctly detect UTF-16 (BE and LE) or UTF-8 BOMs.
- Deprecated
-
Default:
utf8
# Keyof Strings Only -
keyofStringsOnly
This flag changes the
keyof
type operator to returnstring
instead ofstring | number
when applied to a type with a string index signature.This flag is used to help people keep this behavior from before TypeScript 2.9’s release .
- Deprecated
-
Released:
# No Implicit Use Strict -
noImplicitUseStrict
You shouldn’t need this. By default, when emitting a module file to a non-ES6 target, TypeScript emits a
"use strict";
prologue at the top of the file. This setting disables the prologue.TypeScript will unify type parameters when comparing two generic functions.
ts
TrytypeA = <T ,U >(x :T ,y :U ) => [T ,U ];typeB = <S >(x :S ,y :S ) => [S ,S ];functionf (a :A ,b :B ) {b =a ; // Ok =a b ; // Error}This flag can be used to remove that check.
-
Released:
# Out -
out
Use
outFile
instead.The
out
option computes the final file location in a way that is not predictable or consistent. This option is retained for backward compatibility only and is deprecated.- Deprecated
-
Related:
-
# Suppress Excess Property Errors -
suppressExcessPropertyErrors
This disables reporting of excess property errors, such as the one shown in the following example:
ts
TrytypePoint = {x : number;y : number };constObject literal may only specify known properties, and 'm' does not exist in type 'Point'.2353Object literal may only specify known properties, and 'm' does not exist in type 'Point'.p :Point = {x : 1,y : 3, : 10 };m This flag was added to help people migrate to the stricter checking of new object literals in TypeScript 1.6 .
We don’t recommend using this flag in a modern codebase, you can suppress one-off cases where you need it using
// @ts-ignore
.Turning
suppressImplicitAnyIndexErrors
on suppresses reporting the error about implicit anys when indexing into objects, as shown in the following example:ts
Tryconstobj = {x : 10 };Element implicitly has an 'any' type because expression of type '"foo"' can't be used to index type '{ x: number; }'. Property 'foo' does not exist on type '{ x: number; }'.7053Element implicitly has an 'any' type because expression of type '"foo"' can't be used to index type '{ x: number; }'. Property 'foo' does not exist on type '{ x: number; }'.console .log (obj ["foo"]);Using
suppressImplicitAnyIndexErrors
is quite a drastic approach. It is recommended to use a@ts-ignore
comment instead:ts
Tryconstobj = {x : 10 };// @ts-ignoreconsole .log (obj ["foo"]);-
Related:
-
# Language and Environment
# Emit Decorator Metadata -
emitDecoratorMetadata
Enables experimental support for emitting type metadata for decorators which works with the module
reflect-metadata
.For example, here is the TypeScript
ts
TryfunctionLogMethod (target : any,propertyKey : string | symbol,descriptor :PropertyDescriptor ) {console .log (target );console .log (propertyKey );console .log (descriptor );}classDemo {@LogMethod publicfoo (bar : number) {// do nothing}}constdemo = newDemo ();With
emitDecoratorMetadata
not set to true (default) the emitted JavaScript is:ts
Try"use strict";var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;return c > 3 && r && Object.defineProperty(target, key, r), r;};function LogMethod(target, propertyKey, descriptor) {console.log(target);console.log(propertyKey);console.log(descriptor);}class Demo {foo(bar) {// do nothing}}__decorate([LogMethod], Demo.prototype, "foo", null);const demo = new Demo();With
emitDecoratorMetadata
set to true the emitted JavaScript is:ts
Try"use strict";var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d( target, key)) || r;return c > 3 && r && Object.defineProperty(target, key, r), r;};var __metadata = (this && this.__metadata) || function (k, v) {if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);};function LogMethod(target, propertyKey, descriptor) {console.log(target);console.log(propertyKey);console.log(descriptor);}class Demo {foo(bar) {// do nothing}}__decorate([LogMethod,__metadata("design:type", Function),__metadata("design:paramtypes", [Number]),__metadata("design:returntype", void 0)], Demo.prototype, "foo", null);const demo = new Demo();-
Related:
-
# Experimental Decorators -
experimentalDecorators
Enables experimental support for decorators , which is a version of decorators that predates the TC39 standardization process.
Decorators are a language feature which hasn’t yet been fully ratified into the JavaScript specification. This means that the implementation version in TypeScript may differ from the implementation in JavaScript when it it decided by TC39.
You can find out more about decorator support in TypeScript in the handbook .
-
Related:
-
# 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
calls -
react-jsx
: Emit.js
files with the JSX changed to_jsx
calls -
react-jsxdev
: Emit.js
files with the JSX changed to_jsx
calls -
preserve
: Emit.jsx
files with the JSX unchanged -
react-native
: Emit.js
files with the JSX unchanged
For example
This sample code:
tsxexport const HelloWorld = () => <h1>Hello world</h1>;Default:
"react"
tsx
Tryimport React from 'react';export const HelloWorld = () => React.createElement("h1", null, "Hello world");Preserve:
"preserve"
tsx
Tryimport React from 'react';export const HelloWorld = () => <h1>Hello world</h1>;React Native:
"react-native"
tsx
Tryimport React from 'react';export const HelloWorld = () => <h1>Hello world</h1>;React 17 transform:
"react-jsx"
[1]tsx
Tryimport { jsx as _jsx } from "react/jsx-runtime";export const HelloWorld = () => _jsx("h1", { children: "Hello world" });React 17 dev transform:
"react-jsxdev"
[1]tsx
Tryimport { 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: 9, columnNumber: 32 }, this);-
Allowed:
-
preserve
-
react
-
react-native
-
react-jsx
-
react-jsxdev
-
Related:
-
Released:
# JSX Factory -
jsxFactory
Changes the function called in
.js
files when compiling JSX Elements using the classic JSX runtime. The most common change is to use"h"
or"preact.h"
instead of the default"React.createElement"
if usingpreact
.For example, this TSX file:
tsximport { h } from "preact";const HelloWorld = () => <div>Hello</div>;With
jsxFactory: "h"
looks like:tsx
Tryconst preact_1 = require("preact");const HelloWorld = () => (0, preact_1.h)("div", null, "Hello");This option can be used on a per-file basis too similar to Babel’s
/** @jsx h */
directive .tsx
Try/** @jsx h */import {Cannot find module 'preact' or its corresponding type declarations.2307Cannot find module 'preact' or its corresponding type declarations.h } from"preact" ;constHelloWorld = () => <div >Hello</div >;The factory chosen will also affect where the
JSX
namespace is looked up (for type checking information) before falling back to the global one.If the factory is defined as
React.createElement
(the default), the compiler will check forReact.JSX
before checking for a globalJSX
. If the factory is defined ash
, it will check forh.JSX
before a globalJSX
.-
Default:
React.createElement
-
Allowed:
-
Any identifier or dotted identifier.
-
Related:
-
# JSX Fragment Factory -
jsxFragmentFactory
Specify the JSX fragment factory function to use when targeting react JSX emit with
jsxFactory
compiler option is specified, e.g.Fragment
.For example with this TSConfig:
{" ": {" ": "esnext"," ": "commonjs"," ": "react"," ": "h"," ": "Fragment"}}This TSX file:
tsximport { h, Fragment } from "preact";const HelloWorld = () => (<><div>Hello</div></>);Would look like:
tsx
Tryconst preact_1 = require("preact");const HelloWorld = () => ((0, preact_1.h)(preact_1.Fragment, null,(0, preact_1.h)("div", null, "Hello")));This option can be used on a per-file basis too similar to Babel’s
/* @jsxFrag h */
directive .For example:
tsx
Try/** @jsx h *//** @jsxFrag Fragment */import {Cannot find module 'preact' or its corresponding type declarations.2307Cannot find module 'preact' or its corresponding type declarations.h ,Fragment } from"preact" ;constHelloWorld = () => (<><div >Hello</div ></>);-
Default:
React.Fragment
-
Related:
-
Released:
# JSX Import Source -
jsxImportSource
Declares the module specifier to be used for importing the
jsx
andjsxs
factory functions when usingjsx
as"react-jsx"
or"react-jsxdev"
which were introduced in TypeScript 4.1.With React 17 the library supports a new form of JSX transformation via a separate import.
For example with this code:
tsximport React from "react";function App() {return <h1>Hello World</h1>;}Using this TSConfig:
{" ": {" ": "esnext"," ": "commonjs"," ": "react-jsx"}}The emitted JavaScript from TypeScript is:
tsx
Try"use strict";Object.defineProperty(exports, "__esModule", { value: true });const jsx_runtime_1 = require("react/jsx-runtime");function App() {return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" });}For example if you wanted to use
"jsxImportSource": "preact"
, you need a tsconfig like:{" ": {" ": "esnext"," ": "commonjs"," ": "react-jsx"," ": "preact"," ": ["preact"]}}Which generates code like:
tsx
Tryfunction App() {return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" });}exports.App = App;Alternatively, you can use a per-file pragma to set this option, for example:
tsx/** @jsxImportSource preact */export function App() {return <h1>Hello World</h1>;}Would add
preact/jsx-runtime
as an import for the_jsx
factory.Note: In order for this to work like you would expect, your
tsx
file must include anexport
orimport
so that it is considered a module.-
Default:
react
-
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 (likedocument
). TypeScript also includes APIs for newer JS features matching thetarget
you specify; for example the definition forMap
is available iftarget
isES6
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
-
Related:
-
Released:
# Module Detection -
moduleDetection
This setting controls how TypeScript determines whether a file is a script or a module .
There are three choices:
"auto"
(default) - TypeScript will not only look for import and export statements, but it will also check whether the"type"
field in apackage.json
is set to"module"
when running withmodule
:nodenext
ornode16
, and check whether the current file is a JSX file when running underjsx
:react-jsx
."legacy"
- The same behavior as 4.6 and prior, usings import and export statements to determine whether a file is a module."force"
- Ensures that every non-declaration file is treated as a module.-
Default:
"auto": Treat files with imports, exports, import.meta, jsx (with jsx: react-jsx), or esm format (with module: node16+) as modules.
-
Allowed:
-
legacy
-
force
-
Released:
# No Lib -
noLib
Disables the automatic inclusion of any library files. If this option is set,
lib
is ignored.TypeScript cannot compile anything without a set of interfaces for key primitives like:
Array
,Boolean
,Function
,IArguments
,Number
,Object
,RegExp
, andString
. It is expected that if you usenoLib
you will be including your own type definitions for these.-
Related:
-
# React Namespace -
reactNamespace
Use
jsxFactory
instead. Specify the object invoked forcreateElement
when targetingreact
for TSX files.-
Default:
React
# 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 equivalentfunction
expression iftarget
is ES5 or lower.Changing
target
also changes the default value oflib
. You may “mix and match”target
andlib
settings as desired, but you could just settarget
for convenience.For developer platforms like Node there are baselines for the
target
, depending on the type of platform and its version. You can find a set of community organized TSConfigs at tsconfig/bases , which has configurations 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
-
es6
/es2015
-
es2016
-
es2017
-
es2018
-
es2019
-
es2020
-
es2021
-
es2022
-
esnext
-
Released:
# Use Define For Class Fields -
useDefineForClassFields
This flag is used as part of migrating to the upcoming standard version of class fields. TypeScript introduced class fields many years before it was ratified in TC39. The latest version of the upcoming specification has a different runtime behavior to TypeScript’s implementation but the same syntax.
This flag switches to the upcoming ECMA runtime behavior.
You can read more about the transition in the 3.7 release notes .
-
Default:
true
iftarget
isES2022
or higher, includingESNext
;false
otherwise. -
Released:
# Compiler Diagnostics
# Diagnostics -
diagnostics
Used to output diagnostic information for debugging. This command is a subset of
extendedDiagnostics
which are more user-facing results, and easier to interpret.If you have been asked by a TypeScript compiler engineer to give the results using this flag in a compile, in which there is no harm in using
extendedDiagnostics
instead.- Deprecated
-
Default:
-
-
Default:
-
Default:
-
-
Related:
-
-
Default:
In TypeScript 4.5, lib files can be overridden by npm modules, find out more in the blog .
High Level libraries
ContentsES2015
Additional APIs available in ES2015 (also known as ES6) -array.find
,Promise
,Proxy
,Symbol
,Map
,Set
,Reflect
, etc. Alias for “ES2015”ES2016
Additional APIs available in ES2016 -array.include
, etc. 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
,regexp.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.ES2021
Additional APIs available in ES2021 -promise.any
,string.replaceAll
etc.ES2022
Additional APIs available in ES2022 -array.at
,RegExp.hasIndices
, etc.ESNext
Additional APIs available in ESNext - This changes as the JavaScript specification evolves DOM definitions -window
,document
, etc.WebWorker
APIs available in WebWorker contextsScriptHost
APIs for the Windows Script Hosting SystemIndividual library components
This list may be out of date, you can see the full list in the TypeScript source code .
-
Default:
-
Default:
-
-
Default:
-
-
-
Related:
-
-
Related:
-
-
Related:
-
Released:
-
Related:
-
Related:
-
Internal
-
Related:
-
Default:
-
Related:
-
Related:
-
Released:
-
Related:
-
-
Default:
-
Released:
-
Released:
-
-
Default:
-
Related:
-
Related:
-
Released:
-
Related:
-
Default:
-
This feature differs from
typeRoots
in that it is about specifying only the exact types you want included, whereastypeRoots
supports saying you want particular folders. -
-
Related:
-
Default:
-
Default:
-
Default:
-
Default:
-
Released:
-
There are reference pages explaining the theory behind TypeScript’s module resolution and the details of each option .
-
-
Default:
-
Related:
-
Released:
-
Released:
-
Released:
-
Released:
-
Released:
-
Released:
-
Released:
-
-
Released:
-
Default:
-
Default:
If the last path segment in a pattern does not contain a file extension or wildcard character, then it is treated as a directory, and files with supported extensions inside that directory are included (e.g.
.ts
,.tsx
, and.d.ts
by default, with.js
and.jsx
ifallowJs
is set to true). -
Default: