Skip to content
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here
Your logo here

Language and Environment

emitDecoratorMetadata

Enables experimental support for emitting type metadata for decorators which works with the module reflect-metadata.

For example, here is the TypeScript

ts
function 
LogMethod
(
target
: any,
propertyKey
: string | symbol,
descriptor
: PropertyDescriptor) {
console
.
log
(
target
);
console
.
log
(
propertyKey
);
console
.
log
(
descriptor
);
} class
Demo
{
@
LogMethod
public
foo
(
bar
: number) {
// do nothing } } const
demo
= new
Demo
();
Try

With emitDecoratorMetadata not set to true (default) the emitted JavaScript is:

ts
"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();
Try

With emitDecoratorMetadata set to true the emitted JavaScript is:

ts
"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();
Try

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 is decided by TC39.

You can find out more about decorator support in TypeScript in the handbook.

jsx

Controls how JSX constructs are emitted in JavaScript files. This only affects output of JS files that started in .tsx files.

  • react-jsx: Emit .js files with the JSX changed to _jsx calls optimized for production
  • react-jsxdev: Emit .js files with the JSX changed to _jsx calls for development only
  • preserve: Emit .jsx files with the JSX unchanged
  • react-native: Emit .js files with the JSX unchanged
  • react: Emit .js files with JSX changed to the equivalent React.createElement calls

For example

This sample code:

tsx
export const HelloWorld = () => <h1>Hello world</h1>;

React: "react-jsx"[1]

tsx
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HelloWorld = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const HelloWorld = () => (0, jsx_runtime_1.jsx)("h1", { children: "Hello world" });
exports.HelloWorld = HelloWorld;
Try

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

tsx
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HelloWorld = void 0;
const jsx_dev_runtime_1 = require("react/jsx-dev-runtime");
const _jsxFileName = "/home/runner/work/ts-website/ts-website/index.tsx";
const HelloWorld = () => (0, jsx_dev_runtime_1.jsxDEV)("h1", { children: "Hello world" }, void 0, false, { fileName: _jsxFileName, lineNumber: 7, columnNumber: 32 }, this);
exports.HelloWorld = HelloWorld;
Try

Preserve: "preserve"

tsx
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HelloWorld = void 0;
const HelloWorld = () => <h1>Hello world</h1>;
exports.HelloWorld = HelloWorld;
Try

React Native: "react-native"

tsx
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HelloWorld = void 0;
const HelloWorld = () => <h1>Hello world</h1>;
exports.HelloWorld = HelloWorld;
Try

Legacy React runtime: "react"

tsx
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HelloWorld = void 0;
const HelloWorld = () => React.createElement("h1", null, "Hello world");
exports.HelloWorld = HelloWorld;
Try

This option can be used on a per-file basis too using an @jsxRuntime comment.

Always use the classic runtime ("react") for this file:

tsx
/* @jsxRuntime classic */
export const HelloWorld = () => <h1>Hello world</h1>;

Always use the automatic runtime ("react-jsx") for this file:

tsx
/* @jsxRuntime automatic */
export const HelloWorld = () => <h1>Hello world</h1>;

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

For example, this TSX file:

tsx
import { h } from "preact";

const HelloWorld = () => <div>Hello</div>;

With jsxFactory: "h" looks like:

tsx
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const preact_1 = require("preact");
const HelloWorld = () => (0, preact_1.h)("div", null, "Hello");
Try

This option can be used on a per-file basis too similar to Babel's /** @jsx h */ directive.

tsx
/** @jsx h */
import { 
h
} from "preact";
const
HelloWorld
= () => <
div
>Hello</
div
>;
Try

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 for React.JSX before checking for a global JSX. If the factory is defined as h, it will check for h.JSX before a global JSX.

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:

json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "jsx": "react",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment"
  }
}

This TSX file:

tsx
import { h, Fragment } from "preact";

const HelloWorld = () => (
  <>
    <div>Hello</div>
  </>
);

Would look like:

tsx
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const preact_1 = require("preact");
const HelloWorld = () => ((0, preact_1.h)(preact_1.Fragment, null,
    (0, preact_1.h)("div", null, "Hello")));
Try

This option can be used on a per-file basis too similar to Babel's /* @jsxFrag h */ directive.

For example:

tsx
/** @jsx h */
/** @jsxFrag Fragment */

import { 
h
,
Fragment
} from "preact";
const
HelloWorld
= () => (
<> <
div
>Hello</
div
>
</> );
Try

jsxImportSource

Declares the module specifier to be used for importing the jsx and jsxs factory functions when using jsx 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:

tsx
import React from "react";

function App() {
  return <h1>Hello World</h1>;
}

Using this TSConfig:

json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "jsx": "react-jsx"
  }
}

The emitted JavaScript from TypeScript is:

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

For example if you wanted to use "jsxImportSource": "preact", you need a tsconfig like:

json
{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "jsx": "react-jsx",
    "jsxImportSource": "preact",
    "types": ["preact"]
  }
}

Which generates code like:

tsx
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.App = App;
const jsx_runtime_1 = require("preact/jsx-runtime");
function App() {
    return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" });
}
Try

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 an export or import so that it is considered a module.

lib

TypeScript includes a default set of type definitions for built-in JS APIs (like Math), as well as type definitions for things found in browser environments (like document). TypeScript also includes APIs for newer JS features matching the target you specify; for example the definition for Map is available if target is ES6 or newer.

You may want to change these for a few reasons:

  • Your program doesn't run in a browser, so you don't want the "dom" type definitions
  • Your runtime platform provides certain JavaScript API objects (maybe through polyfills), but doesn't yet support the full syntax of a given ECMAScript version
  • You have polyfills or native implementations for some, but not all, of a higher level ECMAScript version

In TypeScript 4.5, lib files can be overridden by npm modules, find out more in the blog.

High Level libraries

NameContents
ES5Core definitions for all ES5 functionality
ES2015Additional APIs available in ES2015 (also known as ES6) - array.find, Promise, Proxy, Symbol, Map, Set, Reflect, etc.
ES6Alias for "ES2015"
ES2016Additional APIs available in ES2016 - array.include, etc.
ES7Alias for "ES2016"
ES2017Additional APIs available in ES2017 - Object.entries, Object.values, Atomics, SharedArrayBuffer, date.formatToParts, typed arrays, etc.
ES2018Additional APIs available in ES2018 - async iterables, promise.finally, Intl.PluralRules, regexp.groups, etc.
ES2019Additional APIs available in ES2019 - array.flat, array.flatMap, Object.fromEntries, string.trimStart, string.trimEnd, etc.
ES2020Additional APIs available in ES2020 - string.matchAll, etc.
ES2021Additional APIs available in ES2021 - promise.any, string.replaceAll etc.
ES2022Additional APIs available in ES2022 - array.at, RegExp.hasIndices, etc.
ES2023Additional APIs available in ES2023 - array.with, array.findLast, array.findLastIndex, array.toSorted, array.toReversed, etc.
ESNextAdditional APIs available in ESNext - This changes as the JavaScript specification evolves
DOMDOM definitions - window, document, etc.
WebWorkerAPIs available in WebWorker contexts
ScriptHostAPIs for the Windows Script Hosting System

Individual library components

Name
DOM.Iterable
ES2015.Core
ES2015.Collection
ES2015.Generator
ES2015.Iterable
ES2015.Promise
ES2015.Proxy
ES2015.Reflect
ES2015.Symbol
ES2015.Symbol.WellKnown
ES2016.Array.Include
ES2017.object
ES2017.Intl
ES2017.SharedMemory
ES2017.String
ES2017.TypedArrays
ES2018.Intl
ES2018.Promise
ES2018.RegExp
ES2019.Array
ES2019.Object
ES2019.String
ES2019.Symbol
ES2020.String
ES2020.Symbol.wellknown
ES2021.Promise
ES2021.String
ES2021.WeakRef
ESNext.AsyncIterable
ESNext.Array
ESNext.Intl
ESNext.Symbol

This list may be out of date, you can see the full list in the TypeScript source code.

libReplacement

TypeScript 4.5 introduced the possibility of substituting the default lib files with custom ones. All built-in library files would first try to be resolved from packages named @typescript/lib-*. For example, you could lock your dom libraries onto a specific version of the @types/web package with the following package.json:

json
{
    "devDependencies": {
       "@typescript/lib-dom": "npm:@types/web@0.0.199"
     }
}

When installed, a package called @typescript/lib-dom should exist, and TypeScript would always look there when searching for lib.dom.d.ts.

The --libReplacement flag allows you to disable this behavior. If you're not using any @typescript/lib-* packages, you can now disable those package lookups with --libReplacement false. In the future, --libReplacement false may become the default, so if you currently rely on the behavior you should consider explicitly enabling it with --libReplacement true.

moduleDetection

  • Allowed: legacy,auto,force

  • Default: "auto": Treat files with imports, exports, import.meta, jsx (with jsx: react-jsx), or esm format (with module: node16+) as modules.

  • Released: 4.7

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 a package.json is set to "module" when running with module: nodenext or node16, and check whether the current file is a JSX file when running under jsx: 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.

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, and String. It is expected that if you use noLib you will be including your own type definitions for these.

reactNamespace

  • Default: React

  • Released: 1.8

Use jsxFactory instead. Specify the object invoked for createElement when targeting react for TSX files.

target

  • Allowed: es3,es5,es6/es2015,es2016,es2017,es2018,es2019,es2020,es2021,es2022,es2023,es2024,es2025,esnext

  • Default: es2023 if module is node20; esnext if module is nodenext; ES5 otherwise.

  • Released: 1.0

Modern browsers support all ES6 features, so ES6 is a good choice. You might choose to set a lower target if your code is deployed to older environments, or a higher target if your code is guaranteed to run in newer environments.

The target setting changes which JS features are downleveled and which are left intact. For example, an arrow function () => this will be turned into an equivalent function expression if target is ES5 or lower.

Changing target also changes the default value of lib. You may "mix and match" target and lib settings as desired, but you could just set target for convenience.

For developer platforms like Node 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.

useDefineForClassFields

  • Default: true if target is ES2022 or higher, including ESNext; false otherwise.

  • Released: 3.7

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.