# The Basics Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](basic-types) * [Everyday Types](everyday-types) * [Narrowing](narrowing) * [More on Functions](functions) * [Object Types](objects) * Type Manipulation * [Creating Types from Types](types-from-types) * [Generics](generics) * [Keyof Type Operator](keyof-types) * [Typeof Type Operator](typeof-types) * [Indexed Access Types](indexed-access-types) * [Conditional Types](conditional-types) * [Mapped Types](mapped-types) * [Template Literal Types](template-literal-types) * [Classes](classes) * [Modules](modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # The Basics Welcome to the first page of the handbook. If this is your first experience with TypeScript - you may want to start at one of the '[Getting Started](../intro#get-started)' guides Each and every value in JavaScript has a set of behaviors you can observe from running different operations. That sounds abstract, but as a quick example, consider some operations we might run on a variable named `message`. // Accessing the property 'toLowerCase' // on 'message' and then calling it message.toLowerCase(); // Calling 'message' message(); If we break this down, the first runnable line of code accesses a property called `toLowerCase` and then calls it. The second one tries to call `message` directly. But assuming we don’t know the value of `message` \- and that’s pretty common - we can’t reliably say what results we’ll get from trying to run any of this code. The behavior of each operation depends entirely on what value we had in the first place. * Is `message` callable? * Does it have a property called `toLowerCase` on it? * If it does, is `toLowerCase` even callable? * If both of these values are callable, what do they return? The answers to these questions are usually things we keep in our heads when we write JavaScript, and we have to hope we got all the details right. Let’s say `message` was defined in the following way. const message = "Hello World!"; As you can probably guess, if we try to run `message.toLowerCase()`, we’ll get the same string only in lower-case. What about that second line of code? If you’re familiar with JavaScript, you’ll know this fails with an exception: TypeError: message is not a function It’d be great if we could avoid mistakes like this. When we run our code, the way that our JavaScript runtime chooses what to do is by figuring out the _type_ of the value - what sorts of behaviors and capabilities it has. That’s part of what that `TypeError` is alluding to - it’s saying that the string `"Hello World!"` cannot be called as a function. For some values, such as the primitives `string` and `number`, we can identify their type at runtime using the `typeof` operator. But for other things like functions, there’s no corresponding runtime mechanism to identify their types. For example, consider this function: function fn(x) { return x.flip(); } We can _observe_ by reading the code that this function will only work if given an object with a callable `flip` property, but JavaScript doesn’t surface this information in a way that we can check while the code is running. The only way in pure JavaScript to tell what `fn` does with a particular value is to call it and see what happens. This kind of behavior makes it hard to predict what the code will do before it runs, which means it’s harder to know what your code is going to do while you’re writing it. Seen in this way, a _type_ is the concept of describing which values can be passed to `fn` and which will crash. JavaScript only truly provides _dynamic_ typing - running the code to see what happens. The alternative is to use a _static_ type system to make predictions about what the code is expected to do _before_ it runs. ## Static type-checking Think back to that `TypeError` we got earlier from trying to call a `string` as a function. _Most people_ don’t like to get any sorts of errors when running their code - those are considered bugs! And when we write new code, we try our best to avoid introducing new bugs. If we add just a bit of code, save our file, re-run the code, and immediately see the error, we might be able to isolate the problem quickly; but that’s not always the case. We might not have tested the feature thoroughly enough, so we might never actually run into a potential error that would be thrown! Or if we were lucky enough to witness the error, we might have ended up doing large refactorings and adding a lot of different code that we’re forced to dig through. Ideally, we could have a tool that helps us find these bugs _before_ our code runs. That’s what a static type-checker like TypeScript does. _Static types systems_ describe the shapes and behaviors of what our values will be when we run our programs. A type-checker like TypeScript uses that information and tells us when things might be going off the rails. const message = "hello!";   message(); Running that last sample with TypeScript will give us an error message before we run the code in the first place. ## Non-exception Failures So far we’ve been discussing certain things like runtime errors - cases where the JavaScript runtime tells us that it thinks something is nonsensical. Those cases come up because [the ECMAScript specification](https://tc39.github.io/ecma262/) has explicit instructions on how the language should behave when it runs into something unexpected. For example, the specification says that trying to call something that isn’t callable should throw an error. Maybe that sounds like “obvious behavior”, but you could imagine that accessing a property that doesn’t exist on an object should throw an error too. Instead, JavaScript gives us different behavior and returns the value `undefined`: const user = { name: "Daniel", age: 26, }; user.location; // returns undefined Ultimately, a static type system has to make the call over what code should be flagged as an error in its system, even if it’s “valid” JavaScript that won’t immediately throw an error. In TypeScript, the following code produces an error about `location` not being defined: const user = { name: "Daniel", age: 26, };   user.location; While sometimes that implies a trade-off in what you can express, the intent is to catch legitimate bugs in our programs. And TypeScript catches _a lot_ of legitimate bugs. For example: typos, const announcement = "Hello World!";   // How quickly can you spot the typos? announcement.toLocaleLowercase(); announcement.toLocalLowerCase();   // We probably meant to write this... announcement.toLocaleLowerCase(); uncalled functions, function flipCoin() { // Meant to be Math.random() return Math.random < 0.5; } or basic logic errors. const value = Math.random() < 0.5 ? "a" : "b"; if (value !== "a") { // ... } else if (value === "b") { // Oops, unreachable } ## Types for Tooling TypeScript can catch bugs when we make mistakes in our code. That’s great, but TypeScript can _also_ prevent us from making those mistakes in the first place. The type-checker has information to check things like whether we’re accessing the right properties on variables and other properties. Once it has that information, it can also start _suggesting_ which properties you might want to use. That means TypeScript can be leveraged for editing code too, and the core type-checker can provide error messages and code completion as you type in the editor. That’s part of what people often refer to when they talk about tooling in TypeScript. import express from "express"; const app = express();   app.get("/", function (req, res) { res.sen });   app.listen(3000); TypeScript takes tooling seriously, and that goes beyond completions and errors as you type. An editor that supports TypeScript can deliver “quick fixes” to automatically fix errors, refactorings to easily re-organize code, and useful navigation features for jumping to definitions of a variable, or finding all references to a given variable. All of this is built on top of the type-checker and is fully cross-platform, so it’s likely that [your favorite editor has TypeScript support available](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Editor- Support). ## `tsc`, the TypeScript compiler We’ve been talking about type-checking, but we haven’t yet used our type- _checker_. Let’s get acquainted with our new friend `tsc`, the TypeScript compiler. First we’ll need to grab it via npm. npm install -g typescript > This installs the TypeScript Compiler `tsc` globally. You can use `npx` or > similar tools if you’d prefer to run `tsc` from a local `node_modules` > package instead. Now let’s move to an empty folder and try writing our first TypeScript program: `hello.ts`: // Greets the world. console.log("Hello world!"); Notice there are no frills here; this “hello world” program looks identical to what you’d write for a “hello world” program in JavaScript. And now let’s type-check it by running the command `tsc` which was installed for us by the `typescript` package. tsc hello.ts Tada! Wait, “tada” _what_ exactly? We ran `tsc` and nothing happened! Well, there were no type errors, so we didn’t get any output in our console since there was nothing to report. But check again - we got some _file_ output instead. If we look in our current directory, we’ll see a `hello.js` file next to `hello.ts`. That’s the output from our `hello.ts` file after `tsc` _compiles_ or _transforms_ it into a plain JavaScript file. And if we check the contents, we’ll see what TypeScript spits out after it processes a `.ts` file: // Greets the world. console.log("Hello world!"); In this case, there was very little for TypeScript to transform, so it looks identical to what we wrote. The compiler tries to emit clean readable code that looks like something a person would write. While that’s not always so easy, TypeScript indents consistently, is mindful of when our code spans across different lines of code, and tries to keep comments around. What about if we _did_ introduce a type-checking error? Let’s rewrite `hello.ts`: // This is an industrial-grade general-purpose greeter function: function greet(person, date) { console.log(`Hello ${person}, today is ${date}!`); }   greet("Brendan"); If we run `tsc hello.ts` again, notice that we get an error on the command line! Expected 2 arguments, but got 1. TypeScript is telling us we forgot to pass an argument to the `greet` function, and rightfully so. So far we’ve only written standard JavaScript, and yet type-checking was still able to find problems with our code. Thanks TypeScript! ## Emitting with Errors One thing you might not have noticed from the last example was that our `hello.js` file changed again. If we open that file up then we’ll see that the contents still basically look the same as our input file. That might be a bit surprising given the fact that `tsc` reported an error about our code, but this is based on one of TypeScript’s core values: much of the time, _you_ will know better than TypeScript. To reiterate from earlier, type-checking code limits the sorts of programs you can run, and so there’s a tradeoff on what sorts of things a type-checker finds acceptable. Most of the time that’s okay, but there are scenarios where those checks get in the way. For example, imagine yourself migrating JavaScript code over to TypeScript and introducing type-checking errors. Eventually you’ll get around to cleaning things up for the type-checker, but that original JavaScript code was already working! Why should converting it over to TypeScript stop you from running it? So TypeScript doesn’t get in your way. Of course, over time, you may want to be a bit more defensive against mistakes, and make TypeScript act a bit more strictly. In that case, you can use the [`noEmitOnError`](../../../tsconfig#noEmitOnError) compiler option. Try changing your `hello.ts` file and running `tsc` with that flag: tsc --noEmitOnError hello.ts You’ll notice that `hello.js` never gets updated. ## Explicit Types Up until now, we haven’t told TypeScript what `person` or `date` are. Let’s edit the code to tell TypeScript that `person` is a `string`, and that `date` should be a `Date` object. We’ll also use the `toDateString()` method on `date`. function greet(person: string, date: Date) { console.log(`Hello ${person}, today is ${date.toDateString()}!`); } What we did was add _type annotations_ on `person` and `date` to describe what types of values `greet` can be called with. You can read that signature as ”`greet` takes a `person` of type `string`, and a `date` of type `Date`“. With this, TypeScript can tell us about other cases where `greet` might have been called incorrectly. For example… function greet(person: string, date: Date) { console.log(`Hello ${person}, today is ${date.toDateString()}!`); }   greet("Maddison", Date()); Huh? TypeScript reported an error on our second argument, but why? Perhaps surprisingly, calling `Date()` in JavaScript returns a `string`. On the other hand, constructing a `Date` with `new Date()` actually gives us what we were expecting. Anyway, we can quickly fix up the error: function greet(person: string, date: Date) { console.log(`Hello ${person}, today is ${date.toDateString()}!`); }   greet("Maddison", new Date()); Keep in mind, we don’t always have to write explicit type annotations. In many cases, TypeScript can even just _infer_ (or “figure out”) the types for us even if we omit them. let msg = "hello there!"; Even though we didn’t tell TypeScript that `msg` had the type `string` it was able to figure that out. That’s a feature, and it’s best not to add annotations when the type system would end up inferring the same type anyway. > Note: The message bubble inside the previous code sample is what your editor > would show if you had hovered over the word. ## Erased Types Let’s take a look at what happens when we compile the above function `greet` with `tsc` to output JavaScript: "use strict"; function greet(person, date) { console.log("Hello ".concat(person, ", today is ").concat(date.toDateString(), "!")); } greet("Maddison", new Date());   Notice two things here: 1. Our `person` and `date` parameters no longer have type annotations. 2. Our “template string” - that string that used backticks (the ``` character) - was converted to plain strings with concatenations. More on that second point later, but let’s now focus on that first point. Type annotations aren’t part of JavaScript (or ECMAScript to be pedantic), so there really aren’t any browsers or other runtimes that can just run TypeScript unmodified. That’s why TypeScript needs a compiler in the first place - it needs some way to strip out or transform any TypeScript-specific code so that you can run it. Most TypeScript-specific code gets erased away, and likewise, here our type annotations were completely erased. > **Remember** : Type annotations never change the runtime behavior of your > program. ## Downleveling One other difference from the above was that our template string was rewritten from `Hello ${person}, today is ${date.toDateString()}!`; to "Hello ".concat(person, ", today is ").concat(date.toDateString(), "!"); Why did this happen? Template strings are a feature from a version of ECMAScript called ECMAScript 2015 (a.k.a. ECMAScript 6, ES2015, ES6, etc. - _don’t ask_). TypeScript has the ability to rewrite code from newer versions of ECMAScript to older ones such as ECMAScript 3 or ECMAScript 5 (a.k.a. ES5). This process of moving from a newer or “higher” version of ECMAScript down to an older or “lower” one is sometimes called _downleveling_. By default TypeScript targets ES5, an extremely old version of ECMAScript. We could have chosen something a little bit more recent by using the [`target`](../../../tsconfig#target) option. Running with `--target es2015` changes TypeScript to target ECMAScript 2015, meaning code should be able to run wherever ECMAScript 2015 is supported. So running `tsc --target es2015 hello.ts` gives us the following output: function greet(person, date) { console.log(`Hello ${person}, today is ${date.toDateString()}!`); } greet("Maddison", new Date()); > While the default target is ES5, the great majority of current browsers > support ES2015. Most developers can therefore safely specify ES2015 or above > as a target, unless compatibility with certain ancient browsers is > important. ## Strictness Different users come to TypeScript looking for different things in a type- checker. Some people are looking for a more loose opt-in experience which can help validate only some parts of their program, and still have decent tooling. This is the default experience with TypeScript, where types are optional, inference takes the most lenient types, and there’s no checking for potentially `null`/`undefined` values. Much like how `tsc` emits in the face of errors, these defaults are put in place to stay out of your way. If you’re migrating existing JavaScript, that might be a desirable first step. In contrast, a lot of users prefer to have TypeScript validate as much as it can straight away, and that’s why the language provides strictness settings as well. These strictness settings turn static type-checking from a switch (either your code is checked or not) into something closer to a dial. The further you turn this dial up, the more TypeScript will check for you. This can require a little extra work, but generally speaking it pays for itself in the long run, and enables more thorough checks and more accurate tooling. When possible, a new codebase should always turn these strictness checks on. TypeScript has several type-checking strictness flags that can be turned on or off, and all of our examples will be written with all of them enabled unless otherwise stated. The [`strict`](../../../tsconfig#strict) flag in the CLI, or `"strict": true` in a [`tsconfig.json`](../tsconfig-json) toggles them all on simultaneously, but we can opt out of them individually. The two biggest ones you should know about are [`noImplicitAny`](../../../tsconfig#noImplicitAny) and [`strictNullChecks`](../../../tsconfig#strictNullChecks). ## `noImplicitAny` Recall that in some places, TypeScript doesn’t try to infer types for us and instead falls back to the most lenient type: `any`. This isn’t the worst thing that can happen - after all, falling back to `any` is just the plain JavaScript experience anyway. However, using `any` often defeats the purpose of using TypeScript in the first place. The more typed your program is, the more validation and tooling you’ll get, meaning you’ll run into fewer bugs as you code. Turning on the [`noImplicitAny`](../../../tsconfig#noImplicitAny) flag will issue an error on any variables whose type is implicitly inferred as `any`. ## `strictNullChecks` By default, values like `null` and `undefined` are assignable to any other type. This can make writing some code easier, but forgetting to handle `null` and `undefined` is the cause of countless bugs in the world - some consider it a [billion dollar mistake](https://www.youtube.com/watch?v=ybrQvs4x0Ps)! The [`strictNullChecks`](../../../tsconfig#strictNullChecks) flag makes handling `null` and `undefined` more explicit, and _spares_ us from worrying about whether we _forgot_ to handle `null` and `undefined`. ##### On this page * Static type-checking * Non-exception Failures * Types for Tooling * tsc, the TypeScript compiler * Emitting with Errors * Explicit Types * Erased Types * Downleveling * Strictness * noImplicitAny * strictNullChecks ##### Is this page helpful? Yes No [ PreviousThe TypeScript Handbook Your first step to learn TypeScript ](../intro) [ NextEveryday Types The language primitives. ](everyday-types) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v2/Basics.md) ❤ Contributors to this page: RC OT RT DR EB 18+ Last updated: Mar 11, 2025 # Classes Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](basic-types) * [Everyday Types](everyday-types) * [Narrowing](narrowing) * [More on Functions](functions) * [Object Types](objects) * Type Manipulation * [Creating Types from Types](types-from-types) * [Generics](generics) * [Keyof Type Operator](keyof-types) * [Typeof Type Operator](typeof-types) * [Indexed Access Types](indexed-access-types) * [Conditional Types](conditional-types) * [Mapped Types](mapped-types) * [Template Literal Types](template-literal-types) * [Classes](classes) * [Modules](modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Classes > Background Reading: > [Classes (MDN)](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Classes) TypeScript offers full support for the `class` keyword introduced in ES2015. As with other JavaScript language features, TypeScript adds type annotations and other syntax to allow you to express relationships between classes and other types. ## Class Members Here’s the most basic class - an empty one: class Point {} This class isn’t very useful yet, so let’s start adding some members. ### Fields A field declaration creates a public writeable property on a class: class Point { x: number; y: number; }   const pt = new Point(); pt.x = 0; pt.y = 0; As with other locations, the type annotation is optional, but will be an implicit `any` if not specified. Fields can also have _initializers_ ; these will run automatically when the class is instantiated: class Point { x = 0; y = 0; }   const pt = new Point(); // Prints 0, 0 console.log(`${pt.x}, ${pt.y}`); Just like with `const`, `let`, and `var`, the initializer of a class property will be used to infer its type: const pt = new Point(); pt.x = "0"; #### `--strictPropertyInitialization` The [`strictPropertyInitialization`](../../../tsconfig#strictPropertyInitialization) setting controls whether class fields need to be initialized in the constructor. class BadGreeter { name: string; } class GoodGreeter { name: string;   constructor() { this.name = "hello"; } } Note that the field needs to be initialized _in the constructor itself_. TypeScript does not analyze methods you invoke from the constructor to detect initializations, because a derived class might override those methods and fail to initialize the members. If you intend to definitely initialize a field through means other than the constructor (for example, maybe an external library is filling in part of your class for you), you can use the _definite assignment assertion operator_ , `!`: class OKGreeter { // Not initialized, but no error name!: string; } ### `readonly` Fields may be prefixed with the `readonly` modifier. This prevents assignments to the field outside of the constructor. class Greeter { readonly name: string = "world";   constructor(otherName?: string) { if (otherName !== undefined) { this.name = otherName; } }   err() { this.name = "not ok"; } } const g = new Greeter(); g.name = "also not ok"; ### Constructors > Background Reading: > [Constructor (MDN)](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Classes/constructor) > Class constructors are very similar to functions. You can add parameters with type annotations, default values, and overloads: class Point { x: number; y: number;   // Normal signature with defaults constructor(x = 0, y = 0) { this.x = x; this.y = y; } } class Point { x: number = 0; y: number = 0;   // Constructor overloads constructor(x: number, y: number); constructor(xy: string); constructor(x: string | number, y: number = 0) { // Code logic here } } There are just a few differences between class constructor signatures and function signatures: * Constructors can’t have type parameters - these belong on the outer class declaration, which we’ll learn about later * Constructors can’t have return type annotations - the class instance type is always what’s returned #### Super Calls Just as in JavaScript, if you have a base class, you’ll need to call `super();` in your constructor body before using any `this.` members: class Base { k = 4; }   class Derived extends Base { constructor() { // Prints a wrong value in ES5; throws exception in ES6 console.log(this.k); super(); } } Forgetting to call `super` is an easy mistake to make in JavaScript, but TypeScript will tell you when it’s necessary. ### Methods > Background Reading: > [Method definitions](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Functions/Method_definitions) > A function property on a class is called a _method_. Methods can use all the same type annotations as functions and constructors: class Point { x = 10; y = 10;   scale(n: number): void { this.x *= n; this.y *= n; } } Other than the standard type annotations, TypeScript doesn’t add anything else new to methods. Note that inside a method body, it is still mandatory to access fields and other methods via `this.`. An unqualified name in a method body will always refer to something in the enclosing scope: let x: number = 0;   class C { x: string = "hello";   m() { // This is trying to modify 'x' from line 1, not the class property x = "world"; } } ### Getters / Setters Classes can also have _accessors_ : class C { _length = 0; get length() { return this._length; } set length(value) { this._length = value; } } > Note that a field-backed get/set pair with no extra logic is very rarely > useful in JavaScript. It’s fine to expose public fields if you don’t need to > add additional logic during the get/set operations. TypeScript has some special inference rules for accessors: * If `get` exists but no `set`, the property is automatically `readonly` * If the type of the setter parameter is not specified, it is inferred from the return type of the getter Since [TypeScript 4.3](https://devblogs.microsoft.com/typescript/announcing- typescript-4-3/), it is possible to have accessors with different types for getting and setting. class Thing { _size = 0;   get size(): number { return this._size; }   set size(value: string | number | boolean) { let num = Number(value);   // Don't allow NaN, Infinity, etc   if (!Number.isFinite(num)) { this._size = 0; return; }   this._size = num; } } ### Index Signatures Classes can declare index signatures; these work the same as [Index Signatures for other object types](objects#index-signatures): class MyClass { [s: string]: boolean | ((s: string) => boolean);   check(s: string) { return this[s] as boolean; } } Because the index signature type needs to also capture the types of methods, it’s not easy to usefully use these types. Generally it’s better to store indexed data in another place instead of on the class instance itself. ## Class Heritage Like other languages with object-oriented features, classes in JavaScript can inherit from base classes. ### `implements` Clauses You can use an `implements` clause to check that a class satisfies a particular `interface`. An error will be issued if a class fails to correctly implement it: interface Pingable { ping(): void; }   class Sonar implements Pingable { ping() { console.log("ping!"); } }   class Ball implements Pingable { pong() { console.log("pong!"); } } Classes may also implement multiple interfaces, e.g. `class C implements A, B {`. #### Cautions It’s important to understand that an `implements` clause is only a check that the class can be treated as the interface type. It doesn’t change the type of the class or its methods _at all_. A common source of error is to assume that an `implements` clause will change the class type - it doesn’t! interface Checkable { check(name: string): boolean; }   class NameChecker implements Checkable { check(s) { // Notice no error here return s.toLowerCase() === "ok"; } } In this example, we perhaps expected that `s`’s type would be influenced by the `name: string` parameter of `check`. It is not - `implements` clauses don’t change how the class body is checked or its type inferred. Similarly, implementing an interface with an optional property doesn’t create that property: interface A { x: number; y?: number; } class C implements A { x = 0; } const c = new C(); c.y = 10; ### `extends` Clauses > Background Reading: > [extends keyword (MDN)](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Classes/extends) > Classes may `extend` from a base class. A derived class has all the properties and methods of its base class, and can also define additional members. class Animal { move() { console.log("Moving along!"); } }   class Dog extends Animal { woof(times: number) { for (let i = 0; i < times; i++) { console.log("woof!"); } } }   const d = new Dog(); // Base class method d.move(); // Derived class method d.woof(3); #### Overriding Methods > Background Reading: > [super keyword (MDN)](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Operators/super) > A derived class can also override a base class field or property. You can use the `super.` syntax to access base class methods. Note that because JavaScript classes are a simple lookup object, there is no notion of a “super field”. TypeScript enforces that a derived class is always a subtype of its base class. For example, here’s a legal way to override a method: class Base { greet() { console.log("Hello, world!"); } }   class Derived extends Base { greet(name?: string) { if (name === undefined) { super.greet(); } else { console.log(`Hello, ${name.toUpperCase()}`); } } }   const d = new Derived(); d.greet(); d.greet("reader"); It’s important that a derived class follow its base class contract. Remember that it’s very common (and always legal!) to refer to a derived class instance through a base class reference: // Alias the derived instance through a base class reference const b: Base = d; // No problem b.greet(); What if `Derived` didn’t follow `Base`’s contract? class Base { greet() { console.log("Hello, world!"); } }   class Derived extends Base { // Make this parameter required greet(name: string) { console.log(`Hello, ${name.toUpperCase()}`); } } If we compiled this code despite the error, this sample would then crash: const b: Base = new Derived(); // Crashes because "name" will be undefined b.greet(); #### Type-only Field Declarations When `target >= ES2022` or [`useDefineForClassFields`](../../../tsconfig#useDefineForClassFields) is `true`, class fields are initialized after the parent class constructor completes, overwriting any value set by the parent class. This can be a problem when you only want to re-declare a more accurate type for an inherited field. To handle these cases, you can write `declare` to indicate to TypeScript that there should be no runtime effect for this field declaration. interface Animal { dateOfBirth: any; }   interface Dog extends Animal { breed: any; }   class AnimalHouse { resident: Animal; constructor(animal: Animal) { this.resident = animal; } }   class DogHouse extends AnimalHouse { // Does not emit JavaScript code, // only ensures the types are correct declare resident: Dog; constructor(dog: Dog) { super(dog); } } #### Initialization Order The order that JavaScript classes initialize can be surprising in some cases. Let’s consider this code: class Base { name = "base"; constructor() { console.log("My name is " + this.name); } }   class Derived extends Base { name = "derived"; }   // Prints "base", not "derived" const d = new Derived(); What happened here? The order of class initialization, as defined by JavaScript, is: * The base class fields are initialized * The base class constructor runs * The derived class fields are initialized * The derived class constructor runs This means that the base class constructor saw its own value for `name` during its own constructor, because the derived class field initializations hadn’t run yet. #### Inheriting Built-in Types > Note: If you don’t plan to inherit from built-in types like `Array`, > `Error`, `Map`, etc. or your compilation target is explicitly set to > `ES6`/`ES2015` or above, you may skip this section In ES2015, constructors which return an object implicitly substitute the value of `this` for any callers of `super(...)`. It is necessary for generated constructor code to capture any potential return value of `super(...)` and replace it with `this`. As a result, subclassing `Error`, `Array`, and others may no longer work as expected. This is due to the fact that constructor functions for `Error`, `Array`, and the like use ECMAScript 6’s `new.target` to adjust the prototype chain; however, there is no way to ensure a value for `new.target` when invoking a constructor in ECMAScript 5. Other downlevel compilers generally have the same limitation by default. For a subclass like the following: class MsgError extends Error { constructor(m: string) { super(m); } sayHello() { return "hello " + this.message; } } you may find that: * methods may be `undefined` on objects returned by constructing these subclasses, so calling `sayHello` will result in an error. * `instanceof` will be broken between instances of the subclass and their instances, so `(new MsgError()) instanceof MsgError` will return `false`. As a recommendation, you can manually adjust the prototype immediately after any `super(...)` calls. class MsgError extends Error { constructor(m: string) { super(m);   // Set the prototype explicitly. Object.setPrototypeOf(this, MsgError.prototype); }   sayHello() { return "hello " + this.message; } } However, any subclass of `MsgError` will have to manually set the prototype as well. For runtimes that don’t support [`Object.setPrototypeOf`](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf), you may instead be able to use [`__proto__`](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto). Unfortunately, [these workarounds will not work on Internet Explorer 10 and prior](https://msdn.microsoft.com/en-us/library/s4esdbwz\(v=vs.94\).aspx). One can manually copy methods from the prototype onto the instance itself (i.e. `MsgError.prototype` onto `this`), but the prototype chain itself cannot be fixed. ## Member Visibility You can use TypeScript to control whether certain methods or properties are visible to code outside the class. ### `public` The default visibility of class members is `public`. A `public` member can be accessed anywhere: class Greeter { public greet() { console.log("hi!"); } } const g = new Greeter(); g.greet(); Because `public` is already the default visibility modifier, you don’t ever _need_ to write it on a class member, but might choose to do so for style/readability reasons. ### `protected` `protected` members are only visible to subclasses of the class they’re declared in. class Greeter { public greet() { console.log("Hello, " + this.getName()); } protected getName() { return "hi"; } }   class SpecialGreeter extends Greeter { public howdy() { // OK to access protected member here console.log("Howdy, " + this.getName()); } } const g = new SpecialGreeter(); g.greet(); // OK g.getName(); #### Exposure of `protected` members Derived classes need to follow their base class contracts, but may choose to expose a subtype of base class with more capabilities. This includes making `protected` members `public`: class Base { protected m = 10; } class Derived extends Base { // No modifier, so default is 'public' m = 15; } const d = new Derived(); console.log(d.m); // OK Note that `Derived` was already able to freely read and write `m`, so this doesn’t meaningfully alter the “security” of this situation. The main thing to note here is that in the derived class, we need to be careful to repeat the `protected` modifier if this exposure isn’t intentional. #### Cross-hierarchy `protected` access TypeScript doesn’t allow accessing `protected` members of a sibling class in a class hierarchy: class Base { protected x: number = 1; } class Derived1 extends Base { protected x: number = 5; } class Derived2 extends Base { f1(other: Derived2) { other.x = 10; } f2(other: Derived1) { other.x = 10; } } This is because accessing `x` in `Derived2` should only be legal from `Derived2`’s subclasses, and `Derived1` isn’t one of them. Moreover, if accessing `x` through a `Derived1` reference is illegal (which it certainly should be!), then accessing it through a base class reference should never improve the situation. See also [Why Can’t I Access A Protected Member From A Derived Class?](https://blogs.msdn.microsoft.com/ericlippert/2005/11/09/why-cant-i- access-a-protected-member-from-a-derived-class/) which explains more of C#‘s reasoning on the same topic. ### `private` `private` is like `protected`, but doesn’t allow access to the member even from subclasses: class Base { private x = 0; } const b = new Base(); // Can't access from outside the class console.log(b.x); class Derived extends Base { showX() { // Can't access in subclasses console.log(this.x); } } Because `private` members aren’t visible to derived classes, a derived class can’t increase their visibility: class Base { private x = 0; } class Derived extends Base { x = 1; } #### Cross-instance `private` access Different OOP languages disagree about whether different instances of the same class may access each others’ `private` members. While languages like Java, C#, C++, Swift, and PHP allow this, Ruby does not. TypeScript does allow cross-instance `private` access: class A { private x = 10;   public sameAs(other: A) { // No error return other.x === this.x; } } #### Caveats Like other aspects of TypeScript’s type system, `private` and `protected` [are only enforced during type checking](https://www.typescriptlang.org/play?removeComments=true&target=99&ts=4.3.4#code/PTAEGMBsEMGddAEQPYHNQBMCmVoCcsEAHPASwDdoAXLUAM1K0gwQFdZSA7dAKWkoDK4MkSoByBAGJQJLAwAeAWABQIUH0HDSoiTLKUaoUggAW+DHorUsAOlABJcQlhUy4KpACeoLJzrI8cCwMGxU1ABVPIiwhESpMZEJQTmR4lxFQaQxWMm4IZABbIlIYKlJkTlDlXHgkNFAAbxVQTIAjfABrAEEC5FZOeIBeUAAGAG5mmSw8WAroSFIqb2GAIjMiIk8VieVJ8Ar01ncAgAoASkaAXxVr3dUwGoQAYWpMHBgCYn1rekZmNg4eUi0Vi2icoBWJCsNBWoA6WE8AHcAiEwmBgTEtDovtDaMZQLM6PEoQZbA5wSk0q5SO4vD4-AEghZoJwLGYEIRwNBoqAzFRwCZCFUIlFMXECdSiAhId8YZgclx0PsiiVqOVOAAaUAFLAsxWgKiC35MFigfC0FKgSAVVDTSyk+W5dB4fplHVVR6gF7xJrKFotEk- HXIRE9PoDUDDcaTAPTWaceaLZYQlmoPBbHYx- KcQ7HPDnK43FQqfY5+IMDDISPJLCIuqoc47UsuUCofAME3Vzi1r3URvF5QV5A2STtPDdXqunZDgDaYlHnTDrrEAF0dm28B3mDZg6HJwN1+2-hg57ulwNV2NQGoZbjYfNrYiENBwEFaojFiZQK08C-4fFKTVCozWfTgfFgLkeT5AUqiAA). This means that JavaScript runtime constructs like `in` or simple property lookup can still access a `private` or `protected` member: class MySafe { private secretKey = 12345; } // In a JavaScript file... const s = new MySafe(); // Will print 12345 console.log(s.secretKey); `private` also allows access using bracket notation during type checking. This makes `private`-declared fields potentially easier to access for things like unit tests, with the drawback that these fields are _soft private_ and don’t strictly enforce privacy. class MySafe { private secretKey = 12345; }   const s = new MySafe();   // Not allowed during type checking console.log(s.secretKey);   // OK console.log(s["secretKey"]); Unlike TypeScripts’s `private`, JavaScript’s [private fields](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Classes/Private_class_fields) (`#`) remain private after compilation and do not provide the previously mentioned escape hatches like bracket notation access, making them _hard private_. class Dog { #barkAmount = 0; personality = "happy";   constructor() {} } "use strict"; class Dog { #barkAmount = 0; personality = "happy"; constructor() { } }   When compiling to ES2021 or less, TypeScript will use WeakMaps in place of `#`. "use strict"; var _Dog_barkAmount; class Dog { constructor() { _Dog_barkAmount.set(this, 0); this.personality = "happy"; } } _Dog_barkAmount = new WeakMap();   If you need to protect values in your class from malicious actors, you should use mechanisms that offer hard runtime privacy, such as closures, WeakMaps, or private fields. Note that these added privacy checks during runtime could affect performance. ## Static Members > Background Reading: > [Static Members (MDN)](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Classes/static) > Classes may have `static` members. These members aren’t associated with a particular instance of the class. They can be accessed through the class constructor object itself: class MyClass { static x = 0; static printX() { console.log(MyClass.x); } } console.log(MyClass.x); MyClass.printX(); Static members can also use the same `public`, `protected`, and `private` visibility modifiers: class MyClass { private static x = 0; } console.log(MyClass.x); Static members are also inherited: class Base { static getGreeting() { return "Hello world"; } } class Derived extends Base { myGreeting = Derived.getGreeting(); } ### Special Static Names It’s generally not safe/possible to overwrite properties from the `Function` prototype. Because classes are themselves functions that can be invoked with `new`, certain `static` names can’t be used. Function properties like `name`, `length`, and `call` aren’t valid to define as `static` members: class S { static name = "S!"; } ### Why No Static Classes? TypeScript (and JavaScript) don’t have a construct called `static class` the same way as, for example, C# does. Those constructs _only_ exist because those languages force all data and functions to be inside a class; because that restriction doesn’t exist in TypeScript, there’s no need for them. A class with only a single instance is typically just represented as a normal _object_ in JavaScript/TypeScript. For example, we don’t need a “static class” syntax in TypeScript because a regular object (or even top-level function) will do the job just as well: // Unnecessary "static" class class MyStaticClass { static doSomething() {} }   // Preferred (alternative 1) function doSomething() {}   // Preferred (alternative 2) const MyHelperObject = { dosomething() {}, }; ## `static` Blocks in Classes Static blocks allow you to write a sequence of statements with their own scope that can access private fields within the containing class. This means that we can write initialization code with all the capabilities of writing statements, no leakage of variables, and full access to our class’s internals. class Foo { static #count = 0;   get count() { return Foo.#count; }   static { try { const lastInstances = loadLastInstances(); Foo.#count += lastInstances.length; } catch {} } } ## Generic Classes Classes, much like interfaces, can be generic. When a generic class is instantiated with `new`, its type parameters are inferred the same way as in a function call: class Box { contents: Type; constructor(value: Type) { this.contents = value; } }   const b = new Box("hello!"); Classes can use generic constraints and defaults the same way as interfaces. ### Type Parameters in Static Members This code isn’t legal, and it may not be obvious why: class Box { static defaultValue: Type; } Remember that types are always fully erased! At runtime, there’s only _one_ `Box.defaultValue` property slot. This means that setting `Box.defaultValue` (if that were possible) would _also_ change `Box.defaultValue` \- not good. The `static` members of a generic class can never refer to the class’s type parameters. ## `this` at Runtime in Classes > Background Reading: > [this keyword (MDN)](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Operators/this) > It’s important to remember that TypeScript doesn’t change the runtime behavior of JavaScript, and that JavaScript is somewhat famous for having some peculiar runtime behaviors. JavaScript’s handling of `this` is indeed unusual: class MyClass { name = "MyClass"; getName() { return this.name; } } const c = new MyClass(); const obj = { name: "obj", getName: c.getName, };   // Prints "obj", not "MyClass" console.log(obj.getName()); Long story short, by default, the value of `this` inside a function depends on _how the function was called_. In this example, because the function was called through the `obj` reference, its value of `this` was `obj` rather than the class instance. This is rarely what you want to happen! TypeScript provides some ways to mitigate or prevent this kind of error. ### Arrow Functions > Background Reading: > [Arrow functions (MDN)](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) > If you have a function that will often be called in a way that loses its `this` context, it can make sense to use an arrow function property instead of a method definition: class MyClass { name = "MyClass"; getName = () => { return this.name; }; } const c = new MyClass(); const g = c.getName; // Prints "MyClass" instead of crashing console.log(g()); This has some trade-offs: * The `this` value is guaranteed to be correct at runtime, even for code not checked with TypeScript * This will use more memory, because each class instance will have its own copy of each function defined this way * You can’t use `super.getName` in a derived class, because there’s no entry in the prototype chain to fetch the base class method from ### `this` parameters In a method or function definition, an initial parameter named `this` has special meaning in TypeScript. These parameters are erased during compilation: // TypeScript input with 'this' parameter function fn(this: SomeType, x: number) { /* ... */ } // JavaScript output function fn(x) { /* ... */ } TypeScript checks that calling a function with a `this` parameter is done so with a correct context. Instead of using an arrow function, we can add a `this` parameter to method definitions to statically enforce that the method is called correctly: class MyClass { name = "MyClass"; getName(this: MyClass) { return this.name; } } const c = new MyClass(); // OK c.getName();   // Error, would crash const g = c.getName; console.log(g()); This method makes the opposite trade-offs of the arrow function approach: * JavaScript callers might still use the class method incorrectly without realizing it * Only one function per class definition gets allocated, rather than one per class instance * Base method definitions can still be called via `super`. ## `this` Types In classes, a special type called `this` refers _dynamically_ to the type of the current class. Let’s see how this is useful: class Box { contents: string = ""; set(value: string) { this.contents = value; return this; } } Here, TypeScript inferred the return type of `set` to be `this`, rather than `Box`. Now let’s make a subclass of `Box`: class ClearableBox extends Box { clear() { this.contents = ""; } }   const a = new ClearableBox(); const b = a.set("hello"); You can also use `this` in a parameter type annotation: class Box { content: string = ""; sameAs(other: this) { return other.content === this.content; } } This is different from writing `other: Box` — if you have a derived class, its `sameAs` method will now only accept other instances of that same derived class: class Box { content: string = ""; sameAs(other: this) { return other.content === this.content; } }   class DerivedBox extends Box { otherContent: string = "?"; }   const base = new Box(); const derived = new DerivedBox(); derived.sameAs(base); ### `this`-based type guards You can use `this is Type` in the return position for methods in classes and interfaces. When mixed with a type narrowing (e.g. `if` statements) the type of the target object would be narrowed to the specified `Type`. class FileSystemObject { isFile(): this is FileRep { return this instanceof FileRep; } isDirectory(): this is Directory { return this instanceof Directory; } isNetworked(): this is Networked & this { return this.networked; } constructor(public path: string, private networked: boolean) {} }   class FileRep extends FileSystemObject { constructor(path: string, public content: string) { super(path, false); } }   class Directory extends FileSystemObject { children: FileSystemObject[]; }   interface Networked { host: string; }   const fso: FileSystemObject = new FileRep("foo/bar.txt", "foo");   if (fso.isFile()) { fso.content; } else if (fso.isDirectory()) { fso.children; } else if (fso.isNetworked()) { fso.host; } A common use-case for a this-based type guard is to allow for lazy validation of a particular field. For example, this case removes an `undefined` from the value held inside box when `hasValue` has been verified to be true: class Box { value?: T;   hasValue(): this is { value: T } { return this.value !== undefined; } }   const box = new Box(); box.value = "Gameboy";   box.value;   if (box.hasValue()) { box.value; } ## Parameter Properties TypeScript offers special syntax for turning a constructor parameter into a class property with the same name and value. These are called _parameter properties_ and are created by prefixing a constructor argument with one of the visibility modifiers `public`, `private`, `protected`, or `readonly`. The resulting field gets those modifier(s): class Params { constructor( public readonly x: number, protected y: number, private z: number ) { // No body necessary } } const a = new Params(1, 2, 3); console.log(a.x); console.log(a.z); ## Class Expressions > Background Reading: > [Class expressions (MDN)](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Operators/class) > Class expressions are very similar to class declarations. The only real difference is that class expressions don’t need a name, though we can refer to them via whatever identifier they ended up bound to: const someClass = class { content: Type; constructor(value: Type) { this.content = value; } };   const m = new someClass("Hello, world"); ## Constructor Signatures JavaScript classes are instantiated with the `new` operator. Given the type of a class itself, the [InstanceType](../utility-types#instancetypetype) utility type models this operation. class Point { createdAt: number; x: number; y: number constructor(x: number, y: number) { this.createdAt = Date.now() this.x = x; this.y = y; } } type PointInstance = InstanceType   function moveRight(point: PointInstance) { point.x += 5; }   const point = new Point(3, 4); moveRight(point); point.x; // => 8 ## `abstract` Classes and Members Classes, methods, and fields in TypeScript may be _abstract_. An _abstract method_ or _abstract field_ is one that hasn’t had an implementation provided. These members must exist inside an _abstract class_ , which cannot be directly instantiated. The role of abstract classes is to serve as a base class for subclasses which do implement all the abstract members. When a class doesn’t have any abstract members, it is said to be _concrete_. Let’s look at an example: abstract class Base { abstract getName(): string;   printName() { console.log("Hello, " + this.getName()); } }   const b = new Base(); We can’t instantiate `Base` with `new` because it’s abstract. Instead, we need to make a derived class and implement the abstract members: class Derived extends Base { getName() { return "world"; } }   const d = new Derived(); d.printName(); Notice that if we forget to implement the base class’s abstract members, we’ll get an error: class Derived extends Base { // forgot to do anything } ### Abstract Construct Signatures Sometimes you want to accept some class constructor function that produces an instance of a class which derives from some abstract class. For example, you might want to write this code: function greet(ctor: typeof Base) { const instance = new ctor(); instance.printName(); } TypeScript is correctly telling you that you’re trying to instantiate an abstract class. After all, given the definition of `greet`, it’s perfectly legal to write this code, which would end up constructing an abstract class: // Bad! greet(Base); Instead, you want to write a function that accepts something with a construct signature: function greet(ctor: new () => Base) { const instance = new ctor(); instance.printName(); } greet(Derived); greet(Base); Now TypeScript correctly tells you about which class constructor functions can be invoked - `Derived` can because it’s concrete, but `Base` cannot. ## Relationships Between Classes In most cases, classes in TypeScript are compared structurally, the same as other types. For example, these two classes can be used in place of each other because they’re identical: class Point1 { x = 0; y = 0; }   class Point2 { x = 0; y = 0; }   // OK const p: Point1 = new Point2(); Similarly, subtype relationships between classes exist even if there’s no explicit inheritance: class Person { name: string; age: number; }   class Employee { name: string; age: number; salary: number; }   // OK const p: Person = new Employee(); This sounds straightforward, but there are a few cases that seem stranger than others. Empty classes have no members. In a structural type system, a type with no members is generally a supertype of anything else. So if you write an empty class (don’t!), anything can be used in place of it: class Empty {}   function fn(x: Empty) { // can't do anything with 'x', so I won't }   // All OK! fn(window); fn({}); fn(fn); ##### On this page * Class Members * Fields * readonly * Constructors * Methods * Getters / Setters * Index Signatures * Class Heritage * implements Clauses * extends Clauses * Member Visibility * public * protected * private * Static Members * Special Static Names * Why No Static Classes? * static Blocks in Classes * Generic Classes * Type Parameters in Static Members * this at Runtime in Classes * Arrow Functions * this parameters * this Types * this-based type guards * Parameter Properties * Class Expressions * Constructor Signatures * abstract Classes and Members * Abstract Construct Signatures * Relationships Between Classes ##### Is this page helpful? Yes No [ NextModules How JavaScript handles communicating across file boundaries. ](modules) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v2/Classes.md) ❤ Contributors to this page: RC OT HA MR U 23+ Last updated: Mar 11, 2025 # Conditional Types Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](basic-types) * [Everyday Types](everyday-types) * [Narrowing](narrowing) * [More on Functions](functions) * [Object Types](objects) * Type Manipulation * [Creating Types from Types](types-from-types) * [Generics](generics) * [Keyof Type Operator](keyof-types) * [Typeof Type Operator](typeof-types) * [Indexed Access Types](indexed-access-types) * [Conditional Types](conditional-types) * [Mapped Types](mapped-types) * [Template Literal Types](template-literal-types) * [Classes](classes) * [Modules](modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Conditional Types At the heart of most useful programs, we have to make decisions based on input. JavaScript programs are no different, but given the fact that values can be easily introspected, those decisions are also based on the types of the inputs. _Conditional types_ help describe the relation between the types of inputs and outputs. interface Animal { live(): void; } interface Dog extends Animal { woof(): void; }   type Example1 = Dog extends Animal ? number : string;   type Example2 = RegExp extends Animal ? number : string; Conditional types take a form that looks a little like conditional expressions (`condition ? trueExpression : falseExpression`) in JavaScript: SomeType extends OtherType ? TrueType : FalseType; When the type on the left of the `extends` is assignable to the one on the right, then you’ll get the type in the first branch (the “true” branch); otherwise you’ll get the type in the latter branch (the “false” branch). From the examples above, conditional types might not immediately seem useful - we can tell ourselves whether or not `Dog extends Animal` and pick `number` or `string`! But the power of conditional types comes from using them with generics. For example, let’s take the following `createLabel` function: interface IdLabel { id: number /* some fields */; } interface NameLabel { name: string /* other fields */; }   function createLabel(id: number): IdLabel; function createLabel(name: string): NameLabel; function createLabel(nameOrId: string | number): IdLabel | NameLabel; function createLabel(nameOrId: string | number): IdLabel | NameLabel { throw "unimplemented"; } These overloads for createLabel describe a single JavaScript function that makes a choice based on the types of its inputs. Note a few things: 1. If a library has to make the same sort of choice over and over throughout its API, this becomes cumbersome. 2. We have to create three overloads: one for each case when we’re _sure_ of the type (one for `string` and one for `number`), and one for the most general case (taking a `string | number`). For every new type `createLabel` can handle, the number of overloads grows exponentially. Instead, we can encode that logic in a conditional type: type NameOrId = T extends number ? IdLabel : NameLabel; We can then use that conditional type to simplify our overloads down to a single function with no overloads. function createLabel(idOrName: T): NameOrId { throw "unimplemented"; }   let a = createLabel("typescript");   let b = createLabel(2.8);   let c = createLabel(Math.random() ? "hello" : 42); ### Conditional Type Constraints Often, the checks in a conditional type will provide us with some new information. Just like narrowing with type guards can give us a more specific type, the true branch of a conditional type will further constrain generics by the type we check against. For example, let’s take the following: type MessageOf = T["message"]; In this example, TypeScript errors because `T` isn’t known to have a property called `message`. We could constrain `T`, and TypeScript would no longer complain: type MessageOf = T["message"];   interface Email { message: string; }   type EmailMessageContents = MessageOf; However, what if we wanted `MessageOf` to take any type, and default to something like `never` if a `message` property isn’t available? We can do this by moving the constraint out and introducing a conditional type: type MessageOf = T extends { message: unknown } ? T["message"] : never;   interface Email { message: string; }   interface Dog { bark(): void; }   type EmailMessageContents = MessageOf;   type DogMessageContents = MessageOf; Within the true branch, TypeScript knows that `T` _will_ have a `message` property. As another example, we could also write a type called `Flatten` that flattens array types to their element types, but leaves them alone otherwise: type Flatten = T extends any[] ? T[number] : T;   // Extracts out the element type. type Str = Flatten;   // Leaves the type alone. type Num = Flatten; When `Flatten` is given an array type, it uses an indexed access with `number` to fetch out `string[]`’s element type. Otherwise, it just returns the type it was given. ### Inferring Within Conditional Types We just found ourselves using conditional types to apply constraints and then extract out types. This ends up being such a common operation that conditional types make it easier. Conditional types provide us with a way to infer from types we compare against in the true branch using the `infer` keyword. For example, we could have inferred the element type in `Flatten` instead of fetching it out “manually” with an indexed access type: type Flatten = Type extends Array ? Item : Type; Here, we used the `infer` keyword to declaratively introduce a new generic type variable named `Item` instead of specifying how to retrieve the element type of `Type` within the true branch. This frees us from having to think about how to dig through and probing apart the structure of the types we’re interested in. We can write some useful helper type aliases using the `infer` keyword. For example, for simple cases, we can extract the return type out from function types: type GetReturnType = Type extends (...args: never[]) => infer Return ? Return : never;   type Num = GetReturnType<() => number>;   type Str = GetReturnType<(x: string) => string>;   type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>; When inferring from a type with multiple call signatures (such as the type of an overloaded function), inferences are made from the _last_ signature (which, presumably, is the most permissive catch-all case). It is not possible to perform overload resolution based on a list of argument types. declare function stringOrNum(x: string): number; declare function stringOrNum(x: number): string; declare function stringOrNum(x: string | number): string | number;   type T1 = ReturnType; ## Distributive Conditional Types When conditional types act on a generic type, they become _distributive_ when given a union type. For example, take the following: type ToArray = Type extends any ? Type[] : never; If we plug a union type into `ToArray`, then the conditional type will be applied to each member of that union. type ToArray = Type extends any ? Type[] : never;   type StrArrOrNumArr = ToArray; What happens here is that `ToArray` distributes on: string | number; and maps over each member type of the union, to what is effectively: ToArray | ToArray; which leaves us with: string[] | number[]; Typically, distributivity is the desired behavior. To avoid that behavior, you can surround each side of the `extends` keyword with square brackets. type ToArrayNonDist = [Type] extends [any] ? Type[] : never;   // 'ArrOfStrOrNum' is no longer a union. type ArrOfStrOrNum = ToArrayNonDist; ##### On this page * Conditional Type Constraints * Inferring Within Conditional Types * Distributive Conditional Types ##### Is this page helpful? Yes No [ PreviousIndexed Access Types Using Type['a'] syntax to access a subset of a type. ](indexed-access-types) [ NextMapped Types Generating types by re-using an existing type. ](mapped-types) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v2/Type%20Manipulation/Conditional%20Types.md) ❤ Contributors to this page: OT BK GF SF NM 9+ Last updated: Mar 11, 2025 # Everyday Types Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](basic-types) * [Everyday Types](everyday-types) * [Narrowing](narrowing) * [More on Functions](functions) * [Object Types](objects) * Type Manipulation * [Creating Types from Types](types-from-types) * [Generics](generics) * [Keyof Type Operator](keyof-types) * [Typeof Type Operator](typeof-types) * [Indexed Access Types](indexed-access-types) * [Conditional Types](conditional-types) * [Mapped Types](mapped-types) * [Template Literal Types](template-literal-types) * [Classes](classes) * [Modules](modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Everyday Types In this chapter, we’ll cover some of the most common types of values you’ll find in JavaScript code, and explain the corresponding ways to describe those types in TypeScript. This isn’t an exhaustive list, and future chapters will describe more ways to name and use other types. Types can also appear in many more _places_ than just type annotations. As we learn about the types themselves, we’ll also learn about the places where we can refer to these types to form new constructs. We’ll start by reviewing the most basic and common types you might encounter when writing JavaScript or TypeScript code. These will later form the core building blocks of more complex types. ## The primitives: `string`, `number`, and `boolean` JavaScript has three very commonly used [primitives](https://developer.mozilla.org/en-US/docs/Glossary/Primitive): `string`, `number`, and `boolean`. Each has a corresponding type in TypeScript. As you might expect, these are the same names you’d see if you used the JavaScript `typeof` operator on a value of those types: * `string` represents string values like `"Hello, world"` * `number` is for numbers like `42`. JavaScript does not have a special runtime value for integers, so there’s no equivalent to `int` or `float` \- everything is simply `number` * `boolean` is for the two values `true` and `false` > The type names `String`, `Number`, and `Boolean` (starting with capital > letters) are legal, but refer to some special built-in types that will very > rarely appear in your code. _Always_ use `string`, `number`, or `boolean` > for types. ## Arrays To specify the type of an array like `[1, 2, 3]`, you can use the syntax `number[]`; this syntax works for any type (e.g. `string[]` is an array of strings, and so on). You may also see this written as `Array`, which means the same thing. We’ll learn more about the syntax `T` when we cover _generics_. > Note that `[number]` is a different thing; refer to the section on > [Tuples](objects#tuple-types). ## `any` TypeScript also has a special type, `any`, that you can use whenever you don’t want a particular value to cause typechecking errors. When a value is of type `any`, you can access any properties of it (which will in turn be of type `any`), call it like a function, assign it to (or from) a value of any type, or pretty much anything else that’s syntactically legal: let obj: any = { x: 0 }; // None of the following lines of code will throw compiler errors. // Using `any` disables all further type checking, and it is assumed // you know the environment better than TypeScript. obj.foo(); obj(); obj.bar = 100; obj = "hello"; const n: number = obj; The `any` type is useful when you don’t want to write out a long type just to convince TypeScript that a particular line of code is okay. ### `noImplicitAny` When you don’t specify a type, and TypeScript can’t infer it from context, the compiler will typically default to `any`. You usually want to avoid this, though, because `any` isn’t type-checked. Use the compiler flag [`noImplicitAny`](../../../tsconfig#noImplicitAny) to flag any implicit `any` as an error. ## Type Annotations on Variables When you declare a variable using `const`, `var`, or `let`, you can optionally add a type annotation to explicitly specify the type of the variable: let myName: string = "Alice"; > TypeScript doesn’t use “types on the left”-style declarations like `int x = > 0;` Type annotations will always go _after_ the thing being typed. In most cases, though, this isn’t needed. Wherever possible, TypeScript tries to automatically _infer_ the types in your code. For example, the type of a variable is inferred based on the type of its initializer: // No type annotation needed -- 'myName' inferred as type 'string' let myName = "Alice"; For the most part you don’t need to explicitly learn the rules of inference. If you’re starting out, try using fewer type annotations than you think - you might be surprised how few you need for TypeScript to fully understand what’s going on. ## Functions Functions are the primary means of passing data around in JavaScript. TypeScript allows you to specify the types of both the input and output values of functions. ### Parameter Type Annotations When you declare a function, you can add type annotations after each parameter to declare what types of parameters the function accepts. Parameter type annotations go after the parameter name: // Parameter type annotation function greet(name: string) { console.log("Hello, " + name.toUpperCase() + "!!"); } When a parameter has a type annotation, arguments to that function will be checked: // Would be a runtime error if executed! greet(42); > Even if you don’t have type annotations on your parameters, TypeScript will > still check that you passed the right number of arguments. ### Return Type Annotations You can also add return type annotations. Return type annotations appear after the parameter list: function getFavoriteNumber(): number { return 26; } Much like variable type annotations, you usually don’t need a return type annotation because TypeScript will infer the function’s return type based on its `return` statements. The type annotation in the above example doesn’t change anything. Some codebases will explicitly specify a return type for documentation purposes, to prevent accidental changes, or just for personal preference. #### Functions Which Return Promises If you want to annotate the return type of a function which returns a promise, you should use the `Promise` type: async function getFavoriteNumber(): Promise { return 26; } ### Anonymous Functions Anonymous functions are a little bit different from function declarations. When a function appears in a place where TypeScript can determine how it’s going to be called, the parameters of that function are automatically given types. Here’s an example: const names = ["Alice", "Bob", "Eve"];   // Contextual typing for function - parameter s inferred to have type string names.forEach(function (s) { console.log(s.toUpperCase()); });   // Contextual typing also applies to arrow functions names.forEach((s) => { console.log(s.toUpperCase()); }); Even though the parameter `s` didn’t have a type annotation, TypeScript used the types of the `forEach` function, along with the inferred type of the array, to determine the type `s` will have. This process is called _contextual typing_ because the _context_ that the function occurred within informs what type it should have. Similar to the inference rules, you don’t need to explicitly learn how this happens, but understanding that it _does_ happen can help you notice when type annotations aren’t needed. Later, we’ll see more examples of how the context that a value occurs in can affect its type. ## Object Types Apart from primitives, the most common sort of type you’ll encounter is an _object type_. This refers to any JavaScript value with properties, which is almost all of them! To define an object type, we simply list its properties and their types. For example, here’s a function that takes a point-like object: // The parameter's type annotation is an object type function printCoord(pt: { x: number; y: number }) { console.log("The coordinate's x value is " + pt.x); console.log("The coordinate's y value is " + pt.y); } printCoord({ x: 3, y: 7 }); Here, we annotated the parameter with a type with two properties - `x` and `y` \- which are both of type `number`. You can use `,` or `;` to separate the properties, and the last separator is optional either way. The type part of each property is also optional. If you don’t specify a type, it will be assumed to be `any`. ### Optional Properties Object types can also specify that some or all of their properties are _optional_. To do this, add a `?` after the property name: function printName(obj: { first: string; last?: string }) { // ... } // Both OK printName({ first: "Bob" }); printName({ first: "Alice", last: "Alisson" }); In JavaScript, if you access a property that doesn’t exist, you’ll get the value `undefined` rather than a runtime error. Because of this, when you _read_ from an optional property, you’ll have to check for `undefined` before using it. function printName(obj: { first: string; last?: string }) { // Error - might crash if 'obj.last' wasn't provided! console.log(obj.last.toUpperCase()); if (obj.last !== undefined) { // OK console.log(obj.last.toUpperCase()); }   // A safe alternative using modern JavaScript syntax: console.log(obj.last?.toUpperCase()); } ## Union Types TypeScript’s type system allows you to build new types out of existing ones using a large variety of operators. Now that we know how to write a few types, it’s time to start _combining_ them in interesting ways. ### Defining a Union Type The first way to combine types you might see is a _union_ type. A union type is a type formed from two or more other types, representing values that may be _any one_ of those types. We refer to each of these types as the union’s _members_. Let’s write a function that can operate on strings or numbers: function printId(id: number | string) { console.log("Your ID is: " + id); } // OK printId(101); // OK printId("202"); // Error printId({ myID: 22342 }); > The separator of the union members is allowed before the first element, so > you could also write this: > > > function printTextOrNumberOrBool( > textOrNumberOrBool: > | string > | number > | boolean > ) { > console.log(textOrNumberOrBool); > } ### Working with Union Types It’s easy to _provide_ a value matching a union type - simply provide a type matching any of the union’s members. If you _have_ a value of a union type, how do you work with it? TypeScript will only allow an operation if it is valid for _every_ member of the union. For example, if you have the union `string | number`, you can’t use methods that are only available on `string`: function printId(id: number | string) { console.log(id.toUpperCase()); } The solution is to _narrow_ the union with code, the same as you would in JavaScript without type annotations. _Narrowing_ occurs when TypeScript can deduce a more specific type for a value based on the structure of the code. For example, TypeScript knows that only a `string` value will have a `typeof` value `"string"`: function printId(id: number | string) { if (typeof id === "string") { // In this branch, id is of type 'string' console.log(id.toUpperCase()); } else { // Here, id is of type 'number' console.log(id); } } Another example is to use a function like `Array.isArray`: function welcomePeople(x: string[] | string) { if (Array.isArray(x)) { // Here: 'x' is 'string[]' console.log("Hello, " + x.join(" and ")); } else { // Here: 'x' is 'string' console.log("Welcome lone traveler " + x); } } Notice that in the `else` branch, we don’t need to do anything special - if `x` wasn’t a `string[]`, then it must have been a `string`. Sometimes you’ll have a union where all the members have something in common. For example, both arrays and strings have a `slice` method. If every member in a union has a property in common, you can use that property without narrowing: // Return type is inferred as number[] | string function getFirstThree(x: number[] | string) { return x.slice(0, 3); } > It might be confusing that a _union_ of types appears to have the _intersection_ of those types’ properties. This is not an accident - the name _union_ comes from type theory. The _union_ `number | string` is composed by taking the union _of the values_ from each type. Notice that given two sets with corresponding facts about each set, only the _intersection_ of those facts applies to the _union_ of the sets themselves. For example, if we had a room of tall people wearing hats, and another room of Spanish speakers wearing hats, after combining those rooms, the only thing we know about _every_ person is that they must be wearing a hat. ## Type Aliases We’ve been using object types and union types by writing them directly in type annotations. This is convenient, but it’s common to want to use the same type more than once and refer to it by a single name. A _type alias_ is exactly that - a _name_ for any _type_. The syntax for a type alias is: type Point = { x: number; y: number; };   // Exactly the same as the earlier example function printCoord(pt: Point) { console.log("The coordinate's x value is " + pt.x); console.log("The coordinate's y value is " + pt.y); }   printCoord({ x: 100, y: 100 }); You can actually use a type alias to give a name to any type at all, not just an object type. For example, a type alias can name a union type: type ID = number | string; Note that aliases are _only_ aliases - you cannot use type aliases to create different/distinct “versions” of the same type. When you use the alias, it’s exactly as if you had written the aliased type. In other words, this code might _look_ illegal, but is OK according to TypeScript because both types are aliases for the same type: type UserInputSanitizedString = string;   function sanitizeInput(str: string): UserInputSanitizedString { return sanitize(str); }   // Create a sanitized input let userInput = sanitizeInput(getInput());   // Can still be re-assigned with a string though userInput = "new input"; ## Interfaces An _interface declaration_ is another way to name an object type: interface Point { x: number; y: number; }   function printCoord(pt: Point) { console.log("The coordinate's x value is " + pt.x); console.log("The coordinate's y value is " + pt.y); }   printCoord({ x: 100, y: 100 }); Just like when we used a type alias above, the example works just as if we had used an anonymous object type. TypeScript is only concerned with the _structure_ of the value we passed to `printCoord` \- it only cares that it has the expected properties. Being concerned only with the structure and capabilities of types is why we call TypeScript a _structurally typed_ type system. ### Differences Between Type Aliases and Interfaces Type aliases and interfaces are very similar, and in many cases you can choose between them freely. Almost all features of an `interface` are available in `type`, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable. `Interface` | `Type` ---|--- Extending an interface ` interface Animal { name: string; } interface Bear extends Animal { honey: boolean; } const bear = getBear(); bear.name; bear.honey; ` | Extending a type via intersections ` type Animal = { name: string; } type Bear = Animal & { honey: boolean; } const bear = getBear(); bear.name; bear.honey; ` Adding new fields to an existing interface ` interface Window { title: string; } interface Window { ts: TypeScriptAPI; } const src = 'const a = "Hello World"'; window.ts.transpileModule(src, {}); ` | A type cannot be changed after being created ` type Window = { title: string; } type Window = { ts: TypeScriptAPI; } // Error: Duplicate identifier 'Window'. ` You’ll learn more about these concepts in later chapters, so don’t worry if you don’t understand all of these right away. * Prior to TypeScript version 4.2, type alias names [_may_ appear in error messages](https://www.typescriptlang.org/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWZWhfYAjABMAMwALA+gbsVjoADqgjKESytQPxCHghAByXigYgBfr8LAsYj8aQMUASbDQcRSExCeCwFiIQh+AKfAYyBiQFgOPyIaikSGLQo0Zj-aazaY+dSaXjLDgAGXgAC9CKhDqAALxJaw2Ib2RzOISuDycLw+ImBYKQflCkWRRD2LXCw6JCxS1JCdJZHJ5RAFIbFJU8ADKC3WzEcnVZaGYE1ABpFnFOmsFhsil2uoHuzwArO9SmAAEIsSFrZB-GgAjjA5gtVN8VCEc1o1C4Q4AGlR2AwO1EsBQoAAbvB-gJ4HhPgB5aDwem-Ph1TCV3AEEirTp4ELtRbTPD4vwKjOfAuioSQHuDXBcnmgACC+eCONFEs73YAPGGZVT5cRyyhiHh7AAON7lsG3vBggB8XGV3l8-nVISOgghxoLq9i7io-AHsayRWGaFrlFauq2rg9qaIGQHwCBqChtKdgRo8TxRjeyB3o+7xAA), sometimes in place of the equivalent anonymous type (which may or may not be desirable). Interfaces will always be named in error messages. * Type aliases may not participate [in declaration merging, but interfaces can](https://www.typescriptlang.org/play?#code/PTAEEEDtQS0gXApgJwGYEMDGjSfdAIx2UQFoB7AB0UkQBMAoEUfO0Wgd1ADd0AbAK6IAzizp16ALgYM4SNFhwBZdAFtV-UAG8GoPaADmNAcMmhh8ZHAMMAvjLkoM2UCvWad+0ARL0A-GYWVpA29gyY5JAWLJAwGnxmbvGgALzauvpGkCZmAEQAjABMAMwALLkANBl6zABi6DB8okR4Jjg+iPSgABboovDk3jjo5pbW1d6+dGb5djLwAJ7UoABKiJTwjThpnpnGpqPBoTLMAJrkArj4kOTwYmycPOhW6AR8IrDQ8N04wmo4HHQCwYi2Waw2W1S6S8HX8gTGITsQA). * Interfaces may only be used to [declare the shapes of objects, not rename primitives](https://www.typescriptlang.org/play?#code/PTAEAkFMCdIcgM6gC4HcD2pIA8CGBbABwBtIl0AzUAKBFAFcEBLAOwHMUBPQs0XFgCahWyGBVwBjMrTDJMAshOhMARpD4tQ6FQCtIE5DWoixk9QEEWAeV37kARlABvaqDegAbrmL1IALlAEZGV2agBfampkbgtrWwMAJlAAXmdXdy8ff0Dg1jZwyLoAVWZ2Lh5QVHUJflAlSFxROsY5fFAWAmk6CnRoLGwmILzQQmV8JmQmDzI-SOiKgGV+CaYAL0gBBdyy1KCQ-Pn1AFFplgA5enw1PtSWS+vCsAAVAAtB4QQWOEMKBuYVUiVCYvYQsUTQcRSBDGMGmKSgAAa-VEgiQe2GLgKQA). * Interface names will [_always_ appear in their original form](https://www.typescriptlang.org/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWY2Q-YAjABMAMwALA+gbsVjNXW8yxySoAADaAA0CCaZbPh1XYqXgOIY0ZgmcK0AA0nyaLFhhGY8F4AHJmEJILCWsgZId4NNfIgGFdcIcUTVfgBlZTOWC8T7kAJ42G4eT+GS42QyRaYbCgXAEEguTzeXyCjDBSAAQSE8Ai0Xsl0K9kcziExDeiQs1lAqSE6SyOTy0AKQ2KHk4p1V6s1OuuoHuzwArMagA) in error messages, but _only_ when they are used by name. * Using interfaces with `extends` [can often be more performant for the compiler](https://github.com/microsoft/TypeScript/wiki/Performance#preferring-interfaces-over-intersections) than type aliases with intersections For the most part, you can choose based on personal preference, and TypeScript will tell you if it needs something to be the other kind of declaration. If you would like a heuristic, use `interface` until you need to use features from `type`. ## Type Assertions Sometimes you will have information about the type of a value that TypeScript can’t know about. For example, if you’re using `document.getElementById`, TypeScript only knows that this will return _some_ kind of `HTMLElement`, but you might know that your page will always have an `HTMLCanvasElement` with a given ID. In this situation, you can use a _type assertion_ to specify a more specific type: const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement; Like a type annotation, type assertions are removed by the compiler and won’t affect the runtime behavior of your code. You can also use the angle-bracket syntax (except if the code is in a `.tsx` file), which is equivalent: const myCanvas = document.getElementById("main_canvas"); > Reminder: Because type assertions are removed at compile-time, there is no > runtime checking associated with a type assertion. There won’t be an > exception or `null` generated if the type assertion is wrong. TypeScript only allows type assertions which convert to a _more specific_ or _less specific_ version of a type. This rule prevents “impossible” coercions like: const x = "hello" as number; Sometimes this rule can be too conservative and will disallow more complex coercions that might be valid. If this happens, you can use two assertions, first to `any` (or `unknown`, which we’ll introduce later), then to the desired type: const a = expr as any as T; ## Literal Types In addition to the general types `string` and `number`, we can refer to _specific_ strings and numbers in type positions. One way to think about this is to consider how JavaScript comes with different ways to declare a variable. Both `var` and `let` allow for changing what is held inside the variable, and `const` does not. This is reflected in how TypeScript creates types for literals. let changingString = "Hello World"; changingString = "Olá Mundo"; // Because `changingString` can represent any possible string, that // is how TypeScript describes it in the type system changingString;   const constantString = "Hello World"; // Because `constantString` can only represent 1 possible string, it // has a literal type representation constantString; By themselves, literal types aren’t very valuable: let x: "hello" = "hello"; // OK x = "hello"; // ... x = "howdy"; It’s not much use to have a variable that can only have one value! But by _combining_ literals into unions, you can express a much more useful concept - for example, functions that only accept a certain set of known values: function printText(s: string, alignment: "left" | "right" | "center") { // ... } printText("Hello, world", "left"); printText("G'day, mate", "centre"); Numeric literal types work the same way: function compare(a: string, b: string): -1 | 0 | 1 { return a === b ? 0 : a > b ? 1 : -1; } Of course, you can combine these with non-literal types: interface Options { width: number; } function configure(x: Options | "auto") { // ... } configure({ width: 100 }); configure("auto"); configure("automatic"); There’s one more kind of literal type: boolean literals. There are only two boolean literal types, and as you might guess, they are the types `true` and `false`. The type `boolean` itself is actually just an alias for the union `true | false`. ### Literal Inference When you initialize a variable with an object, TypeScript assumes that the properties of that object might change values later. For example, if you wrote code like this: const obj = { counter: 0 }; if (someCondition) { obj.counter = 1; } TypeScript doesn’t assume the assignment of `1` to a field which previously had `0` is an error. Another way of saying this is that `obj.counter` must have the type `number`, not `0`, because types are used to determine both _reading_ and _writing_ behavior. The same applies to strings: declare function handleRequest(url: string, method: "GET" | "POST"): void;   const req = { url: "https://example.com", method: "GET" }; handleRequest(req.url, req.method); In the above example `req.method` is inferred to be `string`, not `"GET"`. Because code can be evaluated between the creation of `req` and the call of `handleRequest` which could assign a new string like `"GUESS"` to `req.method`, TypeScript considers this code to have an error. There are two ways to work around this. 1. You can change the inference by adding a type assertion in either location: // Change 1: const req = { url: "https://example.com", method: "GET" as "GET" }; // Change 2 handleRequest(req.url, req.method as "GET"); Change 1 means “I intend for `req.method` to always have the _literal type_ `"GET"`”, preventing the possible assignment of `"GUESS"` to that field after. Change 2 means “I know for other reasons that `req.method` has the value `"GET"`“. 2. You can use `as const` to convert the entire object to be type literals: const req = { url: "https://example.com", method: "GET" } as const; handleRequest(req.url, req.method); The `as const` suffix acts like `const` but for the type system, ensuring that all properties are assigned the literal type instead of a more general version like `string` or `number`. ## `null` and `undefined` JavaScript has two primitive values used to signal absent or uninitialized value: `null` and `undefined`. TypeScript has two corresponding _types_ by the same names. How these types behave depends on whether you have the [`strictNullChecks`](../../../tsconfig#strictNullChecks) option on. ### `strictNullChecks` off With [`strictNullChecks`](../../../tsconfig#strictNullChecks) _off_ , values that might be `null` or `undefined` can still be accessed normally, and the values `null` and `undefined` can be assigned to a property of any type. This is similar to how languages without null checks (e.g. C#, Java) behave. The lack of checking for these values tends to be a major source of bugs; we always recommend people turn [`strictNullChecks`](../../../tsconfig#strictNullChecks) on if it’s practical to do so in their codebase. ### `strictNullChecks` on With [`strictNullChecks`](../../../tsconfig#strictNullChecks) _on_ , when a value is `null` or `undefined`, you will need to test for those values before using methods or properties on that value. Just like checking for `undefined` before using an optional property, we can use _narrowing_ to check for values that might be `null`: function doSomething(x: string | null) { if (x === null) { // do nothing } else { console.log("Hello, " + x.toUpperCase()); } } ### Non-null Assertion Operator (Postfix `!`) TypeScript also has a special syntax for removing `null` and `undefined` from a type without doing any explicit checking. Writing `!` after any expression is effectively a type assertion that the value isn’t `null` or `undefined`: function liveDangerously(x?: number | null) { // No error console.log(x!.toFixed()); } Just like other type assertions, this doesn’t change the runtime behavior of your code, so it’s important to only use `!` when you know that the value _can’t_ be `null` or `undefined`. ## Enums Enums are a feature added to JavaScript by TypeScript which allows for describing a value which could be one of a set of possible named constants. Unlike most TypeScript features, this is _not_ a type-level addition to JavaScript but something added to the language and runtime. Because of this, it’s a feature which you should know exists, but maybe hold off on using unless you are sure. You can read more about enums in the [Enum reference page](../enums). ## Less Common Primitives It’s worth mentioning the rest of the primitives in JavaScript which are represented in the type system. Though we will not go into depth here. #### `bigint` From ES2020 onwards, there is a primitive in JavaScript used for very large integers, `BigInt`: // Creating a bigint via the BigInt function const oneHundred: bigint = BigInt(100);   // Creating a BigInt via the literal syntax const anotherHundred: bigint = 100n; You can learn more about BigInt in [the TypeScript 3.2 release notes](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-2.html#bigint). #### `symbol` There is a primitive in JavaScript used to create a globally unique reference via the function `Symbol()`: const firstName = Symbol("name"); const secondName = Symbol("name");   if (firstName === secondName) { // Can't ever happen } You can learn more about them in [Symbols reference page](../symbols). ##### On this page * The primitives: string, number, and boolean * Arrays * any * noImplicitAny * Type Annotations on Variables * Functions * Parameter Type Annotations * Return Type Annotations * Anonymous Functions * Object Types * Optional Properties * Union Types * Defining a Union Type * Working with Union Types * Type Aliases * Interfaces * Differences Between Type Aliases and Interfaces * Type Assertions * Literal Types * Literal Inference * null and undefined * strictNullChecks off * strictNullChecks on * Non-null Assertion Operator (Postfix !) * Enums * Less Common Primitives ##### Is this page helpful? Yes No [ PreviousThe Basics Step one in learning TypeScript: The basic types. ](basic-types) [ NextNarrowing Understand how TypeScript uses JavaScript knowledge to reduce the amount of type syntax in your projects. ](narrowing) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v2/Everyday%20Types.md) ❤ Contributors to this page: RC OT UG AB DR 31+ Last updated: Mar 11, 2025 # More on Functions Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](basic-types) * [Everyday Types](everyday-types) * [Narrowing](narrowing) * [More on Functions](functions) * [Object Types](objects) * Type Manipulation * [Creating Types from Types](types-from-types) * [Generics](generics) * [Keyof Type Operator](keyof-types) * [Typeof Type Operator](typeof-types) * [Indexed Access Types](indexed-access-types) * [Conditional Types](conditional-types) * [Mapped Types](mapped-types) * [Template Literal Types](template-literal-types) * [Classes](classes) * [Modules](modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # More on Functions Functions are the basic building block of any application, whether they’re local functions, imported from another module, or methods on a class. They’re also values, and just like other values, TypeScript has many ways to describe how functions can be called. Let’s learn about how to write types that describe functions. ## Function Type Expressions The simplest way to describe a function is with a _function type expression_. These types are syntactically similar to arrow functions: function greeter(fn: (a: string) => void) { fn("Hello, World"); }   function printToConsole(s: string) { console.log(s); }   greeter(printToConsole); The syntax `(a: string) => void` means “a function with one parameter, named `a`, of type `string`, that doesn’t have a return value”. Just like with function declarations, if a parameter type isn’t specified, it’s implicitly `any`. > Note that the parameter name is **required**. The function type `(string) => > void` means “a function with a parameter named `string` of type `any`“! Of course, we can use a type alias to name a function type: type GreetFunction = (a: string) => void; function greeter(fn: GreetFunction) { // ... } ## Call Signatures In JavaScript, functions can have properties in addition to being callable. However, the function type expression syntax doesn’t allow for declaring properties. If we want to describe something callable with properties, we can write a _call signature_ in an object type: type DescribableFunction = { description: string; (someArg: number): boolean; }; function doSomething(fn: DescribableFunction) { console.log(fn.description + " returned " + fn(6)); }   function myFunc(someArg: number) { return someArg > 3; } myFunc.description = "default description";   doSomething(myFunc); Note that the syntax is slightly different compared to a function type expression - use `:` between the parameter list and the return type rather than `=>`. ## Construct Signatures JavaScript functions can also be invoked with the `new` operator. TypeScript refers to these as _constructors_ because they usually create a new object. You can write a _construct signature_ by adding the `new` keyword in front of a call signature: type SomeConstructor = { new (s: string): SomeObject; }; function fn(ctor: SomeConstructor) { return new ctor("hello"); } Some objects, like JavaScript’s `Date` object, can be called with or without `new`. You can combine call and construct signatures in the same type arbitrarily: interface CallOrConstruct { (n?: number): string; new (s: string): Date; }   function fn(ctor: CallOrConstruct) { // Passing an argument of type `number` to `ctor` matches it against // the first definition in the `CallOrConstruct` interface. console.log(ctor(10));   // Similarly, passing an argument of type `string` to `ctor` matches it // against the second definition in the `CallOrConstruct` interface. console.log(new ctor("10")); }   fn(Date); ## Generic Functions It’s common to write a function where the types of the input relate to the type of the output, or where the types of two inputs are related in some way. Let’s consider for a moment a function that returns the first element of an array: function firstElement(arr: any[]) { return arr[0]; } This function does its job, but unfortunately has the return type `any`. It’d be better if the function returned the type of the array element. In TypeScript, _generics_ are used when we want to describe a correspondence between two values. We do this by declaring a _type parameter_ in the function signature: function firstElement(arr: Type[]): Type | undefined { return arr[0]; } By adding a type parameter `Type` to this function and using it in two places, we’ve created a link between the input of the function (the array) and the output (the return value). Now when we call it, a more specific type comes out: // s is of type 'string' const s = firstElement(["a", "b", "c"]); // n is of type 'number' const n = firstElement([1, 2, 3]); // u is of type undefined const u = firstElement([]); ### Inference Note that we didn’t have to specify `Type` in this sample. The type was _inferred_ \- chosen automatically - by TypeScript. We can use multiple type parameters as well. For example, a standalone version of `map` would look like this: function map(arr: Input[], func: (arg: Input) => Output): Output[] { return arr.map(func); }   // Parameter 'n' is of type 'string' // 'parsed' is of type 'number[]' const parsed = map(["1", "2", "3"], (n) => parseInt(n)); Note that in this example, TypeScript could infer both the type of the `Input` type parameter (from the given `string` array), as well as the `Output` type parameter based on the return value of the function expression (`number`). ### Constraints We’ve written some generic functions that can work on _any_ kind of value. Sometimes we want to relate two values, but can only operate on a certain subset of values. In this case, we can use a _constraint_ to limit the kinds of types that a type parameter can accept. Let’s write a function that returns the longer of two values. To do this, we need a `length` property that’s a number. We _constrain_ the type parameter to that type by writing an `extends` clause: function longest(a: Type, b: Type) { if (a.length >= b.length) { return a; } else { return b; } }   // longerArray is of type 'number[]' const longerArray = longest([1, 2], [1, 2, 3]); // longerString is of type 'alice' | 'bob' const longerString = longest("alice", "bob"); // Error! Numbers don't have a 'length' property const notOK = longest(10, 100); There are a few interesting things to note in this example. We allowed TypeScript to _infer_ the return type of `longest`. Return type inference also works on generic functions. Because we constrained `Type` to `{ length: number }`, we were allowed to access the `.length` property of the `a` and `b` parameters. Without the type constraint, we wouldn’t be able to access those properties because the values might have been some other type without a length property. The types of `longerArray` and `longerString` were inferred based on the arguments. Remember, generics are all about relating two or more values with the same type! Finally, just as we’d like, the call to `longest(10, 100)` is rejected because the `number` type doesn’t have a `.length` property. ### Working with Constrained Values Here’s a common error when working with generic constraints: function minimumLength( obj: Type, minimum: number ): Type { if (obj.length >= minimum) { return obj; } else { return { length: minimum }; } } It might look like this function is OK - `Type` is constrained to `{ length: number }`, and the function either returns `Type` or a value matching that constraint. The problem is that the function promises to return the _same_ kind of object as was passed in, not just _some_ object matching the constraint. If this code were legal, you could write code that definitely wouldn’t work: // 'arr' gets value { length: 6 } const arr = minimumLength([1, 2, 3], 6); // and crashes here because arrays have // a 'slice' method, but not the returned object! console.log(arr.slice(0)); ### Specifying Type Arguments TypeScript can usually infer the intended type arguments in a generic call, but not always. For example, let’s say you wrote a function to combine two arrays: function combine(arr1: Type[], arr2: Type[]): Type[] { return arr1.concat(arr2); } Normally it would be an error to call this function with mismatched arrays: const arr = combine([1, 2, 3], ["hello"]); If you intended to do this, however, you could manually specify `Type`: const arr = combine([1, 2, 3], ["hello"]); ### Guidelines for Writing Good Generic Functions Writing generic functions is fun, and it can be easy to get carried away with type parameters. Having too many type parameters or using constraints where they aren’t needed can make inference less successful, frustrating callers of your function. #### Push Type Parameters Down Here are two ways of writing a function that appear similar: function firstElement1(arr: Type[]) { return arr[0]; }   function firstElement2(arr: Type) { return arr[0]; }   // a: number (good) const a = firstElement1([1, 2, 3]); // b: any (bad) const b = firstElement2([1, 2, 3]); These might seem identical at first glance, but `firstElement1` is a much better way to write this function. Its inferred return type is `Type`, but `firstElement2`’s inferred return type is `any` because TypeScript has to resolve the `arr[0]` expression using the constraint type, rather than “waiting” to resolve the element during a call. > **Rule** : When possible, use the type parameter itself rather than > constraining it #### Use Fewer Type Parameters Here’s another pair of similar functions: function filter1(arr: Type[], func: (arg: Type) => boolean): Type[] { return arr.filter(func); }   function filter2 boolean>( arr: Type[], func: Func ): Type[] { return arr.filter(func); } We’ve created a type parameter `Func` that _doesn’t relate two values_. That’s always a red flag, because it means callers wanting to specify type arguments have to manually specify an extra type argument for no reason. `Func` doesn’t do anything but make the function harder to read and reason about! > **Rule** : Always use as few type parameters as possible #### Type Parameters Should Appear Twice Sometimes we forget that a function might not need to be generic: function greet(s: Str) { console.log("Hello, " + s); }   greet("world"); We could just as easily have written a simpler version: function greet(s: string) { console.log("Hello, " + s); } Remember, type parameters are for _relating the types of multiple values_. If a type parameter is only used once in the function signature, it’s not relating anything. This includes the inferred return type; for example, if `Str` was part of the inferred return type of `greet`, it would be relating the argument and return types, so would be used _twice_ despite appearing only once in the written code. > **Rule** : If a type parameter only appears in one location, strongly > reconsider if you actually need it ## Optional Parameters Functions in JavaScript often take a variable number of arguments. For example, the `toFixed` method of `number` takes an optional digit count: function f(n: number) { console.log(n.toFixed()); // 0 arguments console.log(n.toFixed(3)); // 1 argument } We can model this in TypeScript by marking the parameter as _optional_ with `?`: function f(x?: number) { // ... } f(); // OK f(10); // OK Although the parameter is specified as type `number`, the `x` parameter will actually have the type `number | undefined` because unspecified parameters in JavaScript get the value `undefined`. You can also provide a parameter _default_ : function f(x = 10) { // ... } Now in the body of `f`, `x` will have type `number` because any `undefined` argument will be replaced with `10`. Note that when a parameter is optional, callers can always pass `undefined`, as this simply simulates a “missing” argument: // All OK f(); f(10); f(undefined); ### Optional Parameters in Callbacks Once you’ve learned about optional parameters and function type expressions, it’s very easy to make the following mistakes when writing functions that invoke callbacks: function myForEach(arr: any[], callback: (arg: any, index?: number) => void) { for (let i = 0; i < arr.length; i++) { callback(arr[i], i); } } What people usually intend when writing `index?` as an optional parameter is that they want both of these calls to be legal: myForEach([1, 2, 3], (a) => console.log(a)); myForEach([1, 2, 3], (a, i) => console.log(a, i)); What this _actually_ means is that _`callback` might get invoked with one argument_. In other words, the function definition says that the implementation might look like this: function myForEach(arr: any[], callback: (arg: any, index?: number) => void) { for (let i = 0; i < arr.length; i++) { // I don't feel like providing the index today callback(arr[i]); } } In turn, TypeScript will enforce this meaning and issue errors that aren’t really possible: myForEach([1, 2, 3], (a, i) => { console.log(i.toFixed()); }); In JavaScript, if you call a function with more arguments than there are parameters, the extra arguments are simply ignored. TypeScript behaves the same way. Functions with fewer parameters (of the same types) can always take the place of functions with more parameters. > **Rule** : When writing a function type for a callback, _never_ write an > optional parameter unless you intend to _call_ the function without passing > that argument ## Function Overloads Some JavaScript functions can be called in a variety of argument counts and types. For example, you might write a function to produce a `Date` that takes either a timestamp (one argument) or a month/day/year specification (three arguments). In TypeScript, we can specify a function that can be called in different ways by writing _overload signatures_. To do this, write some number of function signatures (usually two or more), followed by the body of the function: function makeDate(timestamp: number): Date; function makeDate(m: number, d: number, y: number): Date; function makeDate(mOrTimestamp: number, d?: number, y?: number): Date { if (d !== undefined && y !== undefined) { return new Date(y, mOrTimestamp, d); } else { return new Date(mOrTimestamp); } } const d1 = makeDate(12345678); const d2 = makeDate(5, 5, 5); const d3 = makeDate(1, 3); In this example, we wrote two overloads: one accepting one argument, and another accepting three arguments. These first two signatures are called the _overload signatures_. Then, we wrote a function implementation with a compatible signature. Functions have an _implementation_ signature, but this signature can’t be called directly. Even though we wrote a function with two optional parameters after the required one, it can’t be called with two parameters! ### Overload Signatures and the Implementation Signature This is a common source of confusion. Often people will write code like this and not understand why there is an error: function fn(x: string): void; function fn() { // ... } // Expected to be able to call with zero arguments fn(); Again, the signature used to write the function body can’t be “seen” from the outside. > The signature of the _implementation_ is not visible from the outside. When > writing an overloaded function, you should always have _two_ or more > signatures above the implementation of the function. The implementation signature must also be _compatible_ with the overload signatures. For example, these functions have errors because the implementation signature doesn’t match the overloads in a correct way: function fn(x: boolean): void; // Argument type isn't right function fn(x: string): void; function fn(x: boolean) {} function fn(x: string): string; // Return type isn't right function fn(x: number): boolean; function fn(x: string | number) { return "oops"; } ### Writing Good Overloads Like generics, there are a few guidelines you should follow when using function overloads. Following these principles will make your function easier to call, easier to understand, and easier to implement. Let’s consider a function that returns the length of a string or an array: function len(s: string): number; function len(arr: any[]): number; function len(x: any) { return x.length; } This function is fine; we can invoke it with strings or arrays. However, we can’t invoke it with a value that might be a string _or_ an array, because TypeScript can only resolve a function call to a single overload: len(""); // OK len([0]); // OK len(Math.random() > 0.5 ? "hello" : [0]); Because both overloads have the same argument count and same return type, we can instead write a non-overloaded version of the function: function len(x: any[] | string) { return x.length; } This is much better! Callers can invoke this with either sort of value, and as an added bonus, we don’t have to figure out a correct implementation signature. > Always prefer parameters with union types instead of overloads when possible ## Declaring `this` in a Function TypeScript will infer what the `this` should be in a function via code flow analysis, for example in the following: const user = { id: 123,   admin: false, becomeAdmin: function () { this.admin = true; }, }; TypeScript understands that the function `user.becomeAdmin` has a corresponding `this` which is the outer object `user`. `this`, _heh_ , can be enough for a lot of cases, but there are a lot of cases where you need more control over what object `this` represents. The JavaScript specification states that you cannot have a parameter called `this`, and so TypeScript uses that syntax space to let you declare the type for `this` in the function body. interface DB { filterUsers(filter: (this: User) => boolean): User[]; }   const db = getDB(); const admins = db.filterUsers(function (this: User) { return this.admin; }); This pattern is common with callback-style APIs, where another object typically controls when your function is called. Note that you need to use `function` and not arrow functions to get this behavior: interface DB { filterUsers(filter: (this: User) => boolean): User[]; }   const db = getDB(); const admins = db.filterUsers(() => this.admin); ## Other Types to Know About There are some additional types you’ll want to recognize that appear often when working with function types. Like all types, you can use them everywhere, but these are especially relevant in the context of functions. ### `void` `void` represents the return value of functions which don’t return a value. It’s the inferred type any time a function doesn’t have any `return` statements, or doesn’t return any explicit value from those return statements: // The inferred return type is void function noop() { return; } In JavaScript, a function that doesn’t return any value will implicitly return the value `undefined`. However, `void` and `undefined` are not the same thing in TypeScript. There are further details at the end of this chapter. > `void` is not the same as `undefined`. ### `object` The special type `object` refers to any value that isn’t a primitive (`string`, `number`, `bigint`, `boolean`, `symbol`, `null`, or `undefined`). This is different from the _empty object type_ `{ }`, and also different from the global type `Object`. It’s very likely you will never use `Object`. > `object` is not `Object`. **Always** use `object`! Note that in JavaScript, function values are objects: They have properties, have `Object.prototype` in their prototype chain, are `instanceof Object`, you can call `Object.keys` on them, and so on. For this reason, function types are considered to be `object`s in TypeScript. ### `unknown` The `unknown` type represents _any_ value. This is similar to the `any` type, but is safer because it’s not legal to do anything with an `unknown` value: function f1(a: any) { a.b(); // OK } function f2(a: unknown) { a.b(); } This is useful when describing function types because you can describe functions that accept any value without having `any` values in your function body. Conversely, you can describe a function that returns a value of unknown type: function safeParse(s: string): unknown { return JSON.parse(s); }   // Need to be careful with 'obj'! const obj = safeParse(someRandomString); ### `never` Some functions _never_ return a value: function fail(msg: string): never { throw new Error(msg); } The `never` type represents values which are _never_ observed. In a return type, this means that the function throws an exception or terminates execution of the program. `never` also appears when TypeScript determines there’s nothing left in a union. function fn(x: string | number) { if (typeof x === "string") { // do something } else if (typeof x === "number") { // do something else } else { x; // has type 'never'! } } ### `Function` The global type `Function` describes properties like `bind`, `call`, `apply`, and others present on all function values in JavaScript. It also has the special property that values of type `Function` can always be called; these calls return `any`: function doSomething(f: Function) { return f(1, 2, 3); } This is an _untyped function call_ and is generally best avoided because of the unsafe `any` return type. If you need to accept an arbitrary function but don’t intend to call it, the type `() => void` is generally safer. ## Rest Parameters and Arguments > Background Reading: > [Rest Parameters](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Functions/rest_parameters) > [Spread Syntax](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) > ### Rest Parameters In addition to using optional parameters or overloads to make functions that can accept a variety of fixed argument counts, we can also define functions that take an _unbounded_ number of arguments using _rest parameters_. A rest parameter appears after all other parameters, and uses the `...` syntax: function multiply(n: number, ...m: number[]) { return m.map((x) => n * x); } // 'a' gets value [10, 20, 30, 40] const a = multiply(10, 1, 2, 3, 4); In TypeScript, the type annotation on these parameters is implicitly `any[]` instead of `any`, and any type annotation given must be of the form `Array` or `T[]`, or a tuple type (which we’ll learn about later). ### Rest Arguments Conversely, we can _provide_ a variable number of arguments from an iterable object (for example, an array) using the spread syntax. For example, the `push` method of arrays takes any number of arguments: const arr1 = [1, 2, 3]; const arr2 = [4, 5, 6]; arr1.push(...arr2); Note that in general, TypeScript does not assume that arrays are immutable. This can lead to some surprising behavior: // Inferred type is number[] -- "an array with zero or more numbers", // not specifically two numbers const args = [8, 5]; const angle = Math.atan2(...args); The best fix for this situation depends a bit on your code, but in general a `const` context is the most straightforward solution: // Inferred as 2-length tuple const args = [8, 5] as const; // OK const angle = Math.atan2(...args); Using rest arguments may require turning on [`downlevelIteration`](../../../tsconfig#downlevelIteration) when targeting older runtimes. ## Parameter Destructuring > Background Reading: > [Destructuring Assignment](https://developer.mozilla.org/en- > US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) > You can use parameter destructuring to conveniently unpack objects provided as an argument into one or more local variables in the function body. In JavaScript, it looks like this: function sum({ a, b, c }) { console.log(a + b + c); } sum({ a: 10, b: 3, c: 9 }); The type annotation for the object goes after the destructuring syntax: function sum({ a, b, c }: { a: number; b: number; c: number }) { console.log(a + b + c); } This can look a bit verbose, but you can use a named type here as well: // Same as prior example type ABC = { a: number; b: number; c: number }; function sum({ a, b, c }: ABC) { console.log(a + b + c); } ## Assignability of Functions ### Return type `void` The `void` return type for functions can produce some unusual, but expected behavior. Contextual typing with a return type of `void` does **not** force functions to **not** return something. Another way to say this is a contextual function type with a `void` return type (`type voidFunc = () => void`), when implemented, can return _any_ other value, but it will be ignored. Thus, the following implementations of the type `() => void` are valid: type voidFunc = () => void;   const f1: voidFunc = () => { return true; };   const f2: voidFunc = () => true;   const f3: voidFunc = function () { return true; }; And when the return value of one of these functions is assigned to another variable, it will retain the type of `void`: const v1 = f1();   const v2 = f2();   const v3 = f3(); This behavior exists so that the following code is valid even though `Array.prototype.push` returns a number and the `Array.prototype.forEach` method expects a function with a return type of `void`. const src = [1, 2, 3]; const dst = [0];   src.forEach((el) => dst.push(el)); There is one other special case to be aware of, when a literal function definition has a `void` return type, that function must **not** return anything. function f2(): void { // @ts-expect-error return true; }   const f3 = function (): void { // @ts-expect-error return true; }; For more on `void` please refer to these other documentation entries: * [FAQ - “Why are functions returning non-void assignable to function returning void?”](https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-functions-returning-non-void-assignable-to-function-returning-void) ##### On this page * Function Type Expressions * Call Signatures * Construct Signatures * Generic Functions * Inference * Constraints * Working with Constrained Values * Specifying Type Arguments * Guidelines for Writing Good Generic Functions * Optional Parameters * Optional Parameters in Callbacks * Function Overloads * Overload Signatures and the Implementation Signature * Writing Good Overloads * Declaring this in a Function * Other Types to Know About * void * object * unknown * never * Function * Rest Parameters and Arguments * Rest Parameters * Rest Arguments * Parameter Destructuring * Assignability of Functions * Return type void ##### Is this page helpful? Yes No [ PreviousNarrowing Understand how TypeScript uses JavaScript knowledge to reduce the amount of type syntax in your projects. ](narrowing) [ NextObject Types How TypeScript describes the shapes of JavaScript objects. ](objects) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v2/More%20on%20Functions.md) ❤ Contributors to this page: RC OT HA JW SB 38+ Last updated: Mar 11, 2025 # Generics Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](basic-types) * [Everyday Types](everyday-types) * [Narrowing](narrowing) * [More on Functions](functions) * [Object Types](objects) * Type Manipulation * [Creating Types from Types](types-from-types) * [Generics](generics) * [Keyof Type Operator](keyof-types) * [Typeof Type Operator](typeof-types) * [Indexed Access Types](indexed-access-types) * [Conditional Types](conditional-types) * [Mapped Types](mapped-types) * [Template Literal Types](template-literal-types) * [Classes](classes) * [Modules](modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Generics A major part of software engineering is building components that not only have well-defined and consistent APIs, but are also reusable. Components that are capable of working on the data of today as well as the data of tomorrow will give you the most flexible capabilities for building up large software systems. In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is _generics_ , that is, being able to create a component that can work over a variety of types rather than a single one. This allows users to consume these components and use their own types. ## Hello World of Generics To start off, let’s do the “hello world” of generics: the identity function. The identity function is a function that will return back whatever is passed in. You can think of this in a similar way to the `echo` command. Without generics, we would either have to give the identity function a specific type: function identity(arg: number): number { return arg; } Or, we could describe the identity function using the `any` type: function identity(arg: any): any { return arg; } While using `any` is certainly generic in that it will cause the function to accept any and all types for the type of `arg`, we actually are losing the information about what that type was when the function returns. If we passed in a number, the only information we have is that any type could be returned. Instead, we need a way of capturing the type of the argument in such a way that we can also use it to denote what is being returned. Here, we will use a _type variable_ , a special kind of variable that works on types rather than values. function identity(arg: Type): Type { return arg; } We’ve now added a type variable `Type` to the identity function. This `Type` allows us to capture the type the user provides (e.g. `number`), so that we can use that information later. Here, we use `Type` again as the return type. On inspection, we can now see the same type is used for the argument and the return type. This allows us to traffic that type information in one side of the function and out the other. We say that this version of the `identity` function is generic, as it works over a range of types. Unlike using `any`, it’s also just as precise (i.e., it doesn’t lose any information) as the first `identity` function that used numbers for the argument and return type. Once we’ve written the generic identity function, we can call it in one of two ways. The first way is to pass all of the arguments, including the type argument, to the function: let output = identity("myString"); Here we explicitly set `Type` to be `string` as one of the arguments to the function call, denoted using the `<>` around the arguments rather than `()`. The second way is also perhaps the most common. Here we use _type argument inference_ — that is, we want the compiler to set the value of `Type` for us automatically based on the type of the argument we pass in: let output = identity("myString"); Notice that we didn’t have to explicitly pass the type in the angle brackets (`<>`); the compiler just looked at the value `"myString"`, and set `Type` to its type. While type argument inference can be a helpful tool to keep code shorter and more readable, you may need to explicitly pass in the type arguments as we did in the previous example when the compiler fails to infer the type, as may happen in more complex examples. ## Working with Generic Type Variables When you begin to use generics, you’ll notice that when you create generic functions like `identity`, the compiler will enforce that you use any generically typed parameters in the body of the function correctly. That is, that you actually treat these parameters as if they could be any and all types. Let’s take our `identity` function from earlier: function identity(arg: Type): Type { return arg; } What if we want to also log the length of the argument `arg` to the console with each call? We might be tempted to write this: function loggingIdentity(arg: Type): Type { console.log(arg.length); return arg; } When we do, the compiler will give us an error that we’re using the `.length` member of `arg`, but nowhere have we said that `arg` has this member. Remember, we said earlier that these type variables stand in for any and all types, so someone using this function could have passed in a `number` instead, which does not have a `.length` member. Let’s say that we’ve actually intended this function to work on arrays of `Type` rather than `Type` directly. Since we’re working with arrays, the `.length` member should be available. We can describe this just like we would create arrays of other types: function loggingIdentity(arg: Type[]): Type[] { console.log(arg.length); return arg; } You can read the type of `loggingIdentity` as “the generic function `loggingIdentity` takes a type parameter `Type`, and an argument `arg` which is an array of `Type`s, and returns an array of `Type`s.” If we passed in an array of numbers, we’d get an array of numbers back out, as `Type` would bind to `number`. This allows us to use our generic type variable `Type` as part of the types we’re working with, rather than the whole type, giving us greater flexibility. We can alternatively write the sample example this way: function loggingIdentity(arg: Array): Array { console.log(arg.length); // Array has a .length, so no more error return arg; } You may already be familiar with this style of type from other languages. In the next section, we’ll cover how you can create your own generic types like `Array`. ## Generic Types In previous sections, we created generic identity functions that worked over a range of types. In this section, we’ll explore the type of the functions themselves and how to create generic interfaces. The type of generic functions is just like those of non-generic functions, with the type parameters listed first, similarly to function declarations: function identity(arg: Type): Type { return arg; }   let myIdentity: (arg: Type) => Type = identity; We could also have used a different name for the generic type parameter in the type, so long as the number of type variables and how the type variables are used line up. function identity(arg: Type): Type { return arg; }   let myIdentity: (arg: Input) => Input = identity; We can also write the generic type as a call signature of an object literal type: function identity(arg: Type): Type { return arg; }   let myIdentity: { (arg: Type): Type } = identity; Which leads us to writing our first generic interface. Let’s take the object literal from the previous example and move it to an interface: interface GenericIdentityFn { (arg: Type): Type; }   function identity(arg: Type): Type { return arg; }   let myIdentity: GenericIdentityFn = identity; In a similar example, we may want to move the generic parameter to be a parameter of the whole interface. This lets us see what type(s) we’re generic over (e.g. `Dictionary` rather than just `Dictionary`). This makes the type parameter visible to all the other members of the interface. interface GenericIdentityFn { (arg: Type): Type; }   function identity(arg: Type): Type { return arg; }   let myIdentity: GenericIdentityFn = identity; Notice that our example has changed to be something slightly different. Instead of describing a generic function, we now have a non-generic function signature that is a part of a generic type. When we use `GenericIdentityFn`, we now will also need to specify the corresponding type argument (here: `number`), effectively locking in what the underlying call signature will use. Understanding when to put the type parameter directly on the call signature and when to put it on the interface itself will be helpful in describing what aspects of a type are generic. In addition to generic interfaces, we can also create generic classes. Note that it is not possible to create generic enums and namespaces. ## Generic Classes A generic class has a similar shape to a generic interface. Generic classes have a generic type parameter list in angle brackets (`<>`) following the name of the class. class GenericNumber { zeroValue: NumType; add: (x: NumType, y: NumType) => NumType; }   let myGenericNumber = new GenericNumber(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function (x, y) { return x + y; }; This is a pretty literal use of the `GenericNumber` class, but you may have noticed that nothing is restricting it to only use the `number` type. We could have instead used `string` or even more complex objects. let stringNumeric = new GenericNumber(); stringNumeric.zeroValue = ""; stringNumeric.add = function (x, y) { return x + y; };   console.log(stringNumeric.add(stringNumeric.zeroValue, "test")); Just as with interface, putting the type parameter on the class itself lets us make sure all of the properties of the class are working with the same type. As we cover in [our section on classes](classes), a class has two sides to its type: the static side and the instance side. Generic classes are only generic over their instance side rather than their static side, so when working with classes, static members can not use the class’s type parameter. ## Generic Constraints If you remember from an earlier example, you may sometimes want to write a generic function that works on a set of types where you have _some_ knowledge about what capabilities that set of types will have. In our `loggingIdentity` example, we wanted to be able to access the `.length` property of `arg`, but the compiler could not prove that every type had a `.length` property, so it warns us that we can’t make this assumption. function loggingIdentity(arg: Type): Type { console.log(arg.length); return arg; } Instead of working with any and all types, we’d like to constrain this function to work with any and all types that _also_ have the `.length` property. As long as the type has this member, we’ll allow it, but it’s required to have at least this member. To do so, we must list our requirement as a constraint on what `Type` can be. To do so, we’ll create an interface that describes our constraint. Here, we’ll create an interface that has a single `.length` property and then we’ll use this interface and the `extends` keyword to denote our constraint: interface Lengthwise { length: number; }   function loggingIdentity(arg: Type): Type { console.log(arg.length); // Now we know it has a .length property, so no more error return arg; } Because the generic function is now constrained, it will no longer work over any and all types: loggingIdentity(3); Instead, we need to pass in values whose type has all the required properties: loggingIdentity({ length: 10, value: 3 }); ## Using Type Parameters in Generic Constraints You can declare a type parameter that is constrained by another type parameter. For example, here we’d like to get a property from an object given its name. We’d like to ensure that we’re not accidentally grabbing a property that does not exist on the `obj`, so we’ll place a constraint between the two types: function getProperty(obj: Type, key: Key) { return obj[key]; }   let x = { a: 1, b: 2, c: 3, d: 4 };   getProperty(x, "a"); getProperty(x, "m"); ## Using Class Types in Generics When creating factories in TypeScript using generics, it is necessary to refer to class types by their constructor functions. For example, function create(c: { new (): Type }): Type { return new c(); } A more advanced example uses the prototype property to infer and constrain relationships between the constructor function and the instance side of class types. class BeeKeeper { hasMask: boolean = true; }   class ZooKeeper { nametag: string = "Mikle"; }   class Animal { numLegs: number = 4; }   class Bee extends Animal { numLegs = 6; keeper: BeeKeeper = new BeeKeeper(); }   class Lion extends Animal { keeper: ZooKeeper = new ZooKeeper(); }   function createInstance(c: new () => A): A { return new c(); }   createInstance(Lion).keeper.nametag; createInstance(Bee).keeper.hasMask; This pattern is used to power the [mixins](../mixins) design pattern. ## Generic Parameter Defaults By declaring a default for a generic type parameter, you make it optional to specify the corresponding type argument. For example, a function which creates a new `HTMLElement`. Calling the function with no arguments generates a `HTMLDivElement`; calling the function with an element as the first argument generates an element of the argument’s type. You can optionally pass a list of children as well. Previously you would have to define the function as: declare function create(): Container; declare function create(element: T): Container; declare function create( element: T, children: U[] ): Container; With generic parameter defaults we can reduce it to: declare function create( element?: T, children?: U ): Container;   const div = create();   const p = create(new HTMLParagraphElement()); A generic parameter default follows the following rules: * A type parameter is deemed optional if it has a default. * Required type parameters must not follow optional type parameters. * Default types for a type parameter must satisfy the constraint for the type parameter, if it exists. * When specifying type arguments, you are only required to specify type arguments for the required type parameters. Unspecified type parameters will resolve to their default types. * If a default type is specified and inference cannot choose a candidate, the default type is inferred. * A class or interface declaration that merges with an existing class or interface declaration may introduce a default for an existing type parameter. * A class or interface declaration that merges with an existing class or interface declaration may introduce a new type parameter as long as it specifies a default. ## Variance Annotations > This is an advanced feature for solving a very specific problem, and should > only be used in situations where you’ve identified a reason to use it [Covariance and contravariance](https://en.wikipedia.org/wiki/Covariance_and_contravariance_\(computer_science\)) are type theory terms that describe what the relationship between two generic types is. Here’s a brief primer on the concept. For example, if you have an interface representing an object that can `make` a certain type: interface Producer { make(): T; } We can use a `Producer` where a `Producer` is expected, because a `Cat` is an `Animal`. This relationship is called _covariance_ : the relationship from `Producer` to `Producer` is the same as the relationship from `T` to `U`. Conversely, if you have an interface that can `consume` a certain type: interface Consumer { consume: (arg: T) => void; } Then we can use a `Consumer` where a `Consumer` is expected, because any function that is capable of accepting an `Animal` must also be capable of accepting a `Cat`. This relationship is called _contravariance_ : the relationship from `Consumer` to `Consumer` is the same as the relationship from `U` to `T`. Note the reversal of direction as compared to covariance! This is why contravariance “cancels itself out” but covariance doesn’t. In a structural type system like TypeScript’s, covariance and contravariance are naturally emergent behaviors that follow from the definition of types. Even in the absence of generics, we would see covariant (and contravariant) relationships: interface AnimalProducer { make(): Animal; } // A CatProducer can be used anywhere an // Animal producer is expected interface CatProducer { make(): Cat; } TypeScript has a structural type system, so when comparing two types, e.g. to see if a `Producer` can be used where a `Producer` is expected, the usual algorithm would be structurally expand both of those definitions, and compare their structures. However, variance allows for an extremely useful optimization: if `Producer` is covariant on `T`, then we can simply check `Cat` and `Animal` instead, as we know they’ll have the same relationship as `Producer` and `Producer`. Note that this logic can only be used when we’re examining two instantiations of the same type. If we have a `Producer` and a `FastProducer`, there’s no guarantee that `T` and `U` necessarily refer to the same positions in these types, so this check will always be performed structurally. Because variance is a naturally emergent property of structural types, TypeScript automatically _infers_ the variance of every generic type. **In extremely rare cases** involving certain kinds of circular types, this measurement can be inaccurate. If this happens, you can add a variance annotation to a type parameter to force a particular variance: // Contravariant annotation interface Consumer { consume: (arg: T) => void; } // Covariant annotation interface Producer { make(): T; } // Invariant annotation interface ProducerConsumer { consume: (arg: T) => void; make(): T; } Only do this if you are writing the same variance that _should_ occur structurally. > Never write a variance annotation that doesn’t match the structural > variance! It’s critical to reinforce that variance annotations are only in effect during an instantiation-based comparison. They have no effect during a structural comparison. For example, you can’t use variance annotations to “force” a type to be actually invariant: // DON'T DO THIS - variance annotation // does not match structural behavior interface Producer { make(): T; } // Not a type error -- this is a structural // comparison, so variance annotations are // not in effect const p: Producer = { make(): number { return 42; } } Here, the object literal’s `make` function returns `number`, which we might expect to cause an error because `number` isn’t `string | number`. However, this isn’t an instantiation-based comparison, because the object literal is an anonymous type, not a `Producer`. > Variance annotations don’t change structural behavior and are only consulted > in specific situations It’s very important to only write variance annotations if you absolutely know why you’re doing it, what their limitations are, and when they aren’t in effect. Whether TypeScript uses an instantiation-based comparison or structural comparison is not a specified behavior and may change from version to version for correctness or performance reasons, so you should only ever write variance annotations when they match the structural behavior of a type. Don’t use variance annotations to try to “force” a particular variance; this will cause unpredictable behavior in your code. > Do NOT write variance annotations unless they match the structural behavior > of a type Remember, TypeScript can automatically infer variance from your generic types. It’s almost never necessary to write a variance annotation, and you should only do so when you’ve identified a specific need. Variance annotations _do not_ change the structural behavior of a type, and depending on the situation, you might see a structural comparison made when you expected an instantiation- based comparison. Variance annotations can’t be used to modify how types behave in these structural contexts, and shouldn’t be written unless the annotation is the same as the structural definition. Because this is difficult to get right, and TypeScript can correctly infer variance in the vast majority of cases, you should not find yourself writing variance annotations in normal code. > Don’t try to use variance annotations to change typechecking behavior; this > is not what they are for You _may_ find temporary variance annotations useful in a “type debugging” situation, because variance annotations are checked. TypeScript will issue an error if the annotated variance is identifiably wrong: // Error, this interface is definitely contravariant on T interface Foo { consume: (arg: T) => void; } However, variance annotations are allowed to be stricter (e.g. `in out` is valid if the actual variance is covariant). Be sure to remove your variance annotations once you’re done debugging. Lastly, if you’re trying to maximize your typechecking performance, _and_ have run a profiler, _and_ have identified a specific type that’s slow, _and_ have identified variance inference specifically is slow, _and_ have carefully validated the variance annotation you want to write, you _may_ see a small performance benefit in extraordinarily complex types by adding variance annotations. > Don’t try to use variance annotations to change typechecking behavior; this > is not what they are for ##### On this page * Hello World of Generics * Working with Generic Type Variables * Generic Types * Generic Classes * Generic Constraints * Using Type Parameters in Generic Constraints * Using Class Types in Generics * Generic Parameter Defaults * Variance Annotations ##### Is this page helpful? Yes No [ PreviousCreating Types from Types An overview of the ways in which you can create more types from existing types. ](types-from-types) [ NextKeyof Type Operator Using the keyof operator in type contexts. ](keyof-types) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v2/Type%20Manipulation/Generics.md) ❤ Contributors to this page: OT NK DGM SP P 12+ Last updated: Mar 11, 2025 # Indexed Access Types Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](basic-types) * [Everyday Types](everyday-types) * [Narrowing](narrowing) * [More on Functions](functions) * [Object Types](objects) * Type Manipulation * [Creating Types from Types](types-from-types) * [Generics](generics) * [Keyof Type Operator](keyof-types) * [Typeof Type Operator](typeof-types) * [Indexed Access Types](indexed-access-types) * [Conditional Types](conditional-types) * [Mapped Types](mapped-types) * [Template Literal Types](template-literal-types) * [Classes](classes) * [Modules](modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Indexed Access Types We can use an _indexed access type_ to look up a specific property on another type: type Person = { age: number; name: string; alive: boolean }; type Age = Person["age"]; The indexing type is itself a type, so we can use unions, `keyof`, or other types entirely: type I1 = Person["age" | "name"];   type I2 = Person[keyof Person];   type AliveOrName = "alive" | "name"; type I3 = Person[AliveOrName]; You’ll even see an error if you try to index a property that doesn’t exist: type I1 = Person["alve"]; Another example of indexing with an arbitrary type is using `number` to get the type of an array’s elements. We can combine this with `typeof` to conveniently capture the element type of an array literal: const MyArray = [ { name: "Alice", age: 15 }, { name: "Bob", age: 23 }, { name: "Eve", age: 38 }, ];   type Person = typeof MyArray[number]; type Age = typeof MyArray[number]["age"]; // Or type Age2 = Person["age"]; You can only use types when indexing, meaning you can’t use a `const` to make a variable reference: const key = "age"; type Age = Person[key]; However, you can use a type alias for a similar style of refactor: type key = "age"; type Age = Person[key]; ##### On this page ##### Is this page helpful? Yes No [ PreviousTypeof Type Operator Using the typeof operator in type contexts. ](typeof-types) [ NextConditional Types Create types which act like if statements in the type system. ](conditional-types) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v2/Type%20Manipulation/Indexed%20Access%20Types.md) ❤ Contributors to this page: OT Last updated: Mar 11, 2025 # Keyof Type Operator Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](basic-types) * [Everyday Types](everyday-types) * [Narrowing](narrowing) * [More on Functions](functions) * [Object Types](objects) * Type Manipulation * [Creating Types from Types](types-from-types) * [Generics](generics) * [Keyof Type Operator](keyof-types) * [Typeof Type Operator](typeof-types) * [Indexed Access Types](indexed-access-types) * [Conditional Types](conditional-types) * [Mapped Types](mapped-types) * [Template Literal Types](template-literal-types) * [Classes](classes) * [Modules](modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Keyof Type Operator ## The `keyof` type operator The `keyof` operator takes an object type and produces a string or numeric literal union of its keys. The following type `P` is the same type as `type P = "x" | "y"`: type Point = { x: number; y: number }; type P = keyof Point; If the type has a `string` or `number` index signature, `keyof` will return those types instead: type Arrayish = { [n: number]: unknown }; type A = keyof Arrayish;   type Mapish = { [k: string]: boolean }; type M = keyof Mapish; Note that in this example, `M` is `string | number` — this is because JavaScript object keys are always coerced to a string, so `obj[0]` is always the same as `obj["0"]`. `keyof` types become especially useful when combined with mapped types, which we’ll learn more about later. ##### On this page * The keyof type operator ##### Is this page helpful? Yes No [ PreviousGenerics Types which take parameters ](generics) [ NextTypeof Type Operator Using the typeof operator in type contexts. ](typeof-types) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v2/Type%20Manipulation/Keyof%20Type%20Operator.md) ❤ Contributors to this page: OT RM MM S Last updated: Mar 11, 2025 # Mapped Types Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](basic-types) * [Everyday Types](everyday-types) * [Narrowing](narrowing) * [More on Functions](functions) * [Object Types](objects) * Type Manipulation * [Creating Types from Types](types-from-types) * [Generics](generics) * [Keyof Type Operator](keyof-types) * [Typeof Type Operator](typeof-types) * [Indexed Access Types](indexed-access-types) * [Conditional Types](conditional-types) * [Mapped Types](mapped-types) * [Template Literal Types](template-literal-types) * [Classes](classes) * [Modules](modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Mapped Types When you don’t want to repeat yourself, sometimes a type needs to be based on another type. Mapped types build on the syntax for index signatures, which are used to declare the types of properties which have not been declared ahead of time: type OnlyBoolsAndHorses = { [key: string]: boolean | Horse; };   const conforms: OnlyBoolsAndHorses = { del: true, rodney: false, }; A mapped type is a generic type which uses a union of `PropertyKey`s (frequently created [via a `keyof`](indexed-access-types)) to iterate through keys to create a type: type OptionsFlags = { [Property in keyof Type]: boolean; }; In this example, `OptionsFlags` will take all the properties from the type `Type` and change their values to be a boolean. type Features = { darkMode: () => void; newUserProfile: () => void; };   type FeatureOptions = OptionsFlags; ### Mapping Modifiers There are two additional modifiers which can be applied during mapping: `readonly` and `?` which affect mutability and optionality respectively. You can remove or add these modifiers by prefixing with `-` or `+`. If you don’t add a prefix, then `+` is assumed. // Removes 'readonly' attributes from a type's properties type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; };   type LockedAccount = { readonly id: string; readonly name: string; };   type UnlockedAccount = CreateMutable; // Removes 'optional' attributes from a type's properties type Concrete = { [Property in keyof Type]-?: Type[Property]; };   type MaybeUser = { id: string; name?: string; age?: number; };   type User = Concrete; ## Key Remapping via `as` In TypeScript 4.1 and onwards, you can re-map keys in mapped types with an `as` clause in a mapped type: type MappedTypeWithNewProperties = { [Properties in keyof Type as NewKeyType]: Type[Properties] } You can leverage features like [template literal types](template-literal- types) to create new property names from prior ones: type Getters = { [Property in keyof Type as `get${Capitalize}`]: () => Type[Property] };   interface Person { name: string; age: number; location: string; }   type LazyPerson = Getters; You can filter out keys by producing `never` via a conditional type: // Remove the 'kind' property type RemoveKindField = { [Property in keyof Type as Exclude]: Type[Property] };   interface Circle { kind: "circle"; radius: number; }   type KindlessCircle = RemoveKindField; You can map over arbitrary unions, not just unions of `string | number | symbol`, but unions of any type: type EventConfig = { [E in Events as E["kind"]]: (event: E) => void; }   type SquareEvent = { kind: "square", x: number, y: number }; type CircleEvent = { kind: "circle", radius: number };   type Config = EventConfig ### Further Exploration Mapped types work well with other features in this type manipulation section, for example here is [a mapped type using a conditional type](conditional- types) which returns either a `true` or `false` depending on whether an object has the property `pii` set to the literal `true`: type ExtractPII = { [Property in keyof Type]: Type[Property] extends { pii: true } ? true : false; };   type DBFields = { id: { format: "incrementing" }; name: { type: string; pii: true }; };   type ObjectsNeedingGDPRDeletion = ExtractPII; ##### On this page * Mapping Modifiers * Key Remapping via as * Further Exploration ##### Is this page helpful? Yes No [ PreviousConditional Types Create types which act like if statements in the type system. ](conditional-types) [ NextTemplate Literal Types Generating mapping types which change properties via template literal strings. ](template-literal-types) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v2/Type%20Manipulation/Mapped%20Types.md) ❤ Contributors to this page: OT SF L W SGH 5+ Last updated: Mar 11, 2025 # Modules Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](basic-types) * [Everyday Types](everyday-types) * [Narrowing](narrowing) * [More on Functions](functions) * [Object Types](objects) * Type Manipulation * [Creating Types from Types](types-from-types) * [Generics](generics) * [Keyof Type Operator](keyof-types) * [Typeof Type Operator](typeof-types) * [Indexed Access Types](indexed-access-types) * [Conditional Types](conditional-types) * [Mapped Types](mapped-types) * [Template Literal Types](template-literal-types) * [Classes](classes) * [Modules](modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Modules JavaScript has a long history of different ways to handle modularizing code. Having been around since 2012, TypeScript has implemented support for a lot of these formats, but over time the community and the JavaScript specification has converged on a format called ES Modules (or ES6 modules). You might know it as the `import`/`export` syntax. ES Modules was added to the JavaScript spec in 2015, and by 2020 had broad support in most web browsers and JavaScript runtimes. For focus, the handbook will cover both ES Modules and its popular pre-cursor CommonJS `module.exports =` syntax, and you can find information about the other module patterns in the reference section under [Modules](../modules). ## How JavaScript Modules are Defined In TypeScript, just as in ECMAScript 2015, any file containing a top-level `import` or `export` is considered a module. Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well). Modules are executed within their own scope, not in the global scope. This means that variables, functions, classes, etc. declared in a module are not visible outside the module unless they are explicitly exported using one of the export forms. Conversely, to consume a variable, function, class, interface, etc. exported from a different module, it has to be imported using one of the import forms. ## Non-modules Before we start, it’s important to understand what TypeScript considers a module. The JavaScript specification declares that any JavaScript files without an `import` declaration, `export`, or top-level `await` should be considered a script and not a module. Inside a script file variables and types are declared to be in the shared global scope, and it’s assumed that you’ll either use the [`outFile`](../../../tsconfig#outFile) compiler option to join multiple input files into one output file, or use multiple `
Compiler:
Framework:
## Test 1. Run the project 2. As you type on the boxes you should see the message appear/change! ## Debug 1. In Edge, press F12 and click the Debugger tab. 2. Look in the first localhost folder, then scripts/app.ts 3. Put a breakpoint on the line with return. 4. Type in the boxes and confirm that the breakpoint hits in TypeScript code and that inspection works correctly. Congrats you’ve built your own .NET Core project with a TypeScript frontend. ##### On this page * Install ASP.NET Core and TypeScript * Create a new project * Set up the server * Add TypeScript * Add TypeScript code * Add example code * Set up the build * Write a HTML page * Test * Debug ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/tutorials/ASP.NET%20Core.md) ❤ Contributors to this page: BK OT GC DR LZ 14+ Last updated: Mar 11, 2025 # Using Babel with TypeScript Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) # Using Babel with TypeScript ## Babel vs `tsc` for TypeScript When making a modern JavaScript project, you might ask yourself what is the right way to convert files from TypeScript to JavaScript? A lot of the time the answer is _“it depends”_ , or _“someone may have decided for you”_ depending on the project. If you are building your project with an existing framework like [tsdx](https://tsdx.io), [Angular](https://angular.io/), [NestJS](https://nestjs.com/) or any framework mentioned in the [Getting Started](https://www.typescriptlang.org/docs) then this decision is handled for you. However, a useful heuristic could be: * Is your build output mostly the same as your source input files? Use `tsc` * Do you need a build pipeline with multiple potential outputs? Use `babel` for transpiling and `tsc` for type checking ## Babel for transpiling, `tsc` for types This is a common pattern for projects with existing build infrastructure which may have been ported from a JavaScript codebase to TypeScript. This technique is a hybrid approach, using Babel’s [preset- typescript](https://babeljs.io/docs/en/babel-preset-typescript) to generate your JS files, and then using TypeScript to do type checking and `.d.ts` file generation. By using babel’s support for TypeScript, you get the ability to work with existing build pipelines and are more likely to have a faster JS emit time because Babel does not type check your code. #### Type Checking and d.ts file generation The downside to using babel is that you don’t get type checking during the transition from TS to JS. This can mean that type errors which you miss in your editor could sneak through into production code. In addition to that, Babel cannot create `.d.ts` files for your TypeScript which can make it harder to work with your project if it is a library. To fix these issues, you would probably want to set up a command to type check your project using TSC. This likely means duplicating some of your babel config into a corresponding [`tsconfig.json`](../../tsconfig) and ensuring these flags are enabled: "compilerOptions": { // Ensure that .d.ts files are created by tsc, but not .js files "declaration": true, "emitDeclarationOnly": true, // Ensure that Babel can safely transpile files in the TypeScript project "isolatedModules": true } For more information on these flags: * [`isolatedModules`](../../tsconfig#isolatedModules) * [`declaration`](../../tsconfig#declaration), [`emitDeclarationOnly`](../../tsconfig#emitDeclarationOnly) ##### On this page * Babel vs tsc for TypeScript * Babel for transpiling, tsc for types ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/tutorials/Babel%20with%20TypeScript.md) ❤ Contributors to this page: OT SU R US Last updated: Mar 11, 2025 # Basic Types Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) ### This page has been deprecated This handbook page has been replaced, [go to the new page](2/everyday-types) [Go to new page](2/everyday-types) # Basic Types For programs to be useful, we need to be able to work with some of the simplest units of data: numbers, strings, structures, boolean values, and the like. In TypeScript, we support the same types as you would expect in JavaScript, with an extra enumeration type thrown in to help things along. ## Boolean The most basic datatype is the simple true/false value, which JavaScript and TypeScript call a `boolean` value. let isDone: boolean = false; ## Number As in JavaScript, all numbers in TypeScript are either floating point values or BigIntegers. These floating point numbers get the type `number`, while BigIntegers get the type `bigint`. In addition to hexadecimal and decimal literals, TypeScript also supports binary and octal literals introduced in ECMAScript 2015. let decimal: number = 6; let hex: number = 0xf00d; let binary: number = 0b1010; let octal: number = 0o744; let big: bigint = 100n; ## String Another fundamental part of creating programs in JavaScript for webpages and servers alike is working with textual data. As in other languages, we use the type `string` to refer to these textual datatypes. Just like JavaScript, TypeScript also uses double quotes (`"`) or single quotes (`'`) to surround string data. let color: string = "blue"; color = 'red'; You can also use _template strings_ , which can span multiple lines and have embedded expressions. These strings are surrounded by the backtick/backquote (```) character, and embedded expressions are of the form `${ expr }`. let fullName: string = `Bob Bobbington`; let age: number = 37; let sentence: string = `Hello, my name is ${fullName}.   I'll be ${age + 1} years old next month.`; This is equivalent to declaring `sentence` like so: let sentence: string = "Hello, my name is " + fullName + ".\n\n" + "I'll be " + (age + 1) + " years old next month."; ## Array TypeScript, like JavaScript, allows you to work with arrays of values. Array types can be written in one of two ways. In the first, you use the type of the elements followed by `[]` to denote an array of that element type: let list: number[] = [1, 2, 3]; The second way uses a generic array type, `Array`: let list: Array = [1, 2, 3]; ## Tuple Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same. For example, you may want to represent a value as a pair of a `string` and a `number`: // Declare a tuple type let x: [string, number]; // Initialize it x = ["hello", 10]; // OK // Initialize it incorrectly x = [10, "hello"]; // Error When accessing an element with a known index, the correct type is retrieved: // OK console.log(x[0].substring(1));   console.log(x[1].substring(1)); Accessing an element outside the set of known indices fails with an error: x[3] = "world";   console.log(x[5].toString()); ## Enum A helpful addition to the standard set of datatypes from JavaScript is the `enum`. As in languages like C#, an enum is a way of giving more friendly names to sets of numeric values. enum Color { Red, Green, Blue, } let c: Color = Color.Green; By default, enums begin numbering their members starting at `0`. You can change this by manually setting the value of one of its members. For example, we can start the previous example at `1` instead of `0`: enum Color { Red = 1, Green, Blue, } let c: Color = Color.Green; Or, even manually set all the values in the enum: enum Color { Red = 1, Green = 2, Blue = 4, } let c: Color = Color.Green; A handy feature of enums is that you can also go from a numeric value to the name of that value in the enum. For example, if we had the value `2` but weren’t sure what that mapped to in the `Color` enum above, we could look up the corresponding name: enum Color { Red = 1, Green, Blue, } let colorName: string = Color[2];   // Displays 'Green' console.log(colorName); ## Unknown We may need to describe the type of variables that we do not know when we are writing an application. These values may come from dynamic content – e.g. from the user – or we may want to intentionally accept all values in our API. In these cases, we want to provide a type that tells the compiler and future readers that this variable could be anything, so we give it the `unknown` type. let notSure: unknown = 4; notSure = "maybe a string instead";   // OK, definitely a boolean notSure = false; If you have a variable with an unknown type, you can narrow it to something more specific by doing `typeof` checks, comparison checks, or more advanced type guards that will be discussed in a later chapter: declare const maybe: unknown; // 'maybe' could be a string, object, boolean, undefined, or other types const aNumber: number = maybe;   if (maybe === true) { // TypeScript knows that maybe is a boolean now const aBoolean: boolean = maybe; // So, it cannot be a string const aString: string = maybe; }   if (typeof maybe === "string") { // TypeScript knows that maybe is a string const aString: string = maybe; // So, it cannot be a boolean const aBoolean: boolean = maybe; } ## Any In some situations, not all type information is available or its declaration would take an inappropriate amount of effort. These may occur for values from code that has been written without TypeScript or a 3rd party library. In these cases, we might want to opt-out of type checking. To do so, we label these values with the `any` type: declare function getValue(key: string): any; // OK, return value of 'getValue' is not checked const str: string = getValue("myString"); The `any` type is a powerful way to work with existing JavaScript, allowing you to gradually opt-in and opt-out of type checking during compilation. Unlike `unknown`, variables of type `any` allow you to access arbitrary properties, even ones that don’t exist. These properties include functions and TypeScript will not check their existence or type: let looselyTyped: any = 4; // OK, ifItExists might exist at runtime looselyTyped.ifItExists(); // OK, toFixed exists (but the compiler doesn't check) looselyTyped.toFixed();   let strictlyTyped: unknown = 4; strictlyTyped.toFixed(); The `any` will continue to propagate through your objects: let looselyTyped: any = {}; let d = looselyTyped.a.b.c.d; After all, remember that all the convenience of `any` comes at the cost of losing type safety. Type safety is one of the main motivations for using TypeScript and you should try to avoid using `any` when not necessary. ## Void `void` is a little like the opposite of `any`: the absence of having any type at all. You may commonly see this as the return type of functions that do not return a value: function warnUser(): void { console.log("This is my warning message"); } Declaring variables of type `void` is not useful because you can only assign `null` (only if [`strictNullChecks`](../../tsconfig#strictNullChecks) is not specified, see next section) or `undefined` to them: let unusable: void = undefined; // OK if `--strictNullChecks` is not given unusable = null; ## Null and Undefined In TypeScript, both `undefined` and `null` actually have their types named `undefined` and `null` respectively. Much like `void`, they’re not extremely useful on their own: // Not much else we can assign to these variables! let u: undefined = undefined; let n: null = null; By default `null` and `undefined` are subtypes of all other types. That means you can assign `null` and `undefined` to something like `number`. However, when using the [`strictNullChecks`](../../tsconfig#strictNullChecks) flag, `null` and `undefined` are only assignable to `unknown`, `any` and their respective types (the one exception being that `undefined` is also assignable to `void`). This helps avoid _many_ common errors. In cases where you want to pass in either a `string` or `null` or `undefined`, you can use the union type `string | null | undefined`. Union types are an advanced topic that we’ll cover in a later chapter. > As a note: we encourage the use of > [`strictNullChecks`](../../tsconfig#strictNullChecks) when possible, but for > the purposes of this handbook, we will assume it is turned off. ## Never The `never` type represents the type of values that never occur. For instance, `never` is the return type for a function expression or an arrow function expression that always throws an exception or one that never returns. Variables also acquire the type `never` when narrowed by any type guards that can never be true. The `never` type is a subtype of, and assignable to, every type; however, _no_ type is a subtype of, or assignable to, `never` (except `never` itself). Even `any` isn’t assignable to `never`. Some examples of functions returning `never`: // Function returning never must not have a reachable end point function error(message: string): never { throw new Error(message); }   // Inferred return type is never function fail() { return error("Something failed"); }   // Function returning never must not have a reachable end point function infiniteLoop(): never { while (true) {} } ## Object `object` is a type that represents the non-primitive type, i.e. anything that is not `number`, `string`, `boolean`, `bigint`, `symbol`, `null`, or `undefined`. With `object` type, APIs like `Object.create` can be better represented. For example: declare function create(o: object | null): void;   // OK create({ prop: 0 }); create(null); create(undefined); // with `--strictNullChecks` flag enabled, undefined is not a subtype of null   create(42); create("string"); create(false); Generally, you won’t need to use this. ## Type assertions Sometimes you’ll end up in a situation where you’ll know more about a value than TypeScript does. Usually, this will happen when you know the type of some entity could be more specific than its current type. _Type assertions_ are a way to tell the compiler “trust me, I know what I’m doing.” A type assertion is like a type cast in other languages, but it performs no special checking or restructuring of data. It has no runtime impact and is used purely by the compiler. TypeScript assumes that you, the programmer, have performed any special checks that you need. Type assertions have two forms. One is the `as`-syntax: let someValue: unknown = "this is a string";   let strLength: number = (someValue as string).length; The other version is the “angle-bracket” syntax: let someValue: unknown = "this is a string";   let strLength: number = (someValue).length; The two samples are equivalent. Using one over the other is mostly a choice of preference; however, when using TypeScript with JSX, only `as`-style assertions are allowed. ## A note about `let` You may have noticed that so far, we’ve been using the `let` keyword instead of JavaScript’s `var` keyword which you might be more familiar with. The `let` keyword is actually a newer JavaScript construct that TypeScript makes available. You can read in the Handbook Reference on [Variable Declarations](variable-declarations) more about how `let` and `const` fix a lot of the problems with `var`. ## About `Number`, `String`, `Boolean`, `Symbol` and `Object` It can be tempting to think that the types `Number`, `String`, `Boolean`, `Symbol`, or `Object` are the same as the lowercase versions recommended above. These types do not refer to the language primitives however, and almost never should be used as a type. function reverse(s: String): String { return s.split("").reverse().join(""); }   reverse("hello world"); Instead, use the types `number`, `string`, `boolean`, `object` and `symbol`. function reverse(s: string): string { return s.split("").reverse().join(""); }   reverse("hello world"); ##### On this page * Boolean * Number * String * Array * Tuple * Enum * Unknown * Any * Void * Null and Undefined * Never * Object * Type assertions * A note about let * About Number, String, Boolean, Symbol and Object ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v1/Basic%20Types.md) ❤ Contributors to this page: RC OT DR NS MZ 47+ Last updated: Mar 11, 2025 # Classes Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) ### This page has been deprecated This handbook page has been replaced, [go to the new page](2/classes) [Go to new page](2/classes) # Classes Traditional JavaScript uses functions and prototype-based inheritance to build up reusable components, but this may feel a bit awkward to programmers more comfortable with an object-oriented approach, where classes inherit functionality and objects are built from these classes. Starting with ECMAScript 2015, also known as ECMAScript 6, JavaScript programmers can build their applications using this object-oriented class-based approach. In TypeScript, we allow developers to use these techniques now, and compile them down to JavaScript that works across all major browsers and platforms, without having to wait for the next version of JavaScript. ## Classes Let’s take a look at a simple class-based example: class Greeter { greeting: string;   constructor(message: string) { this.greeting = message; }   greet() { return "Hello, " + this.greeting; } }   let greeter = new Greeter("world"); The syntax should look familiar if you’ve used C# or Java before. We declare a new class `Greeter`. This class has three members: a property called `greeting`, a constructor, and a method `greet`. You’ll notice that in the class when we refer to one of the members of the class we prepend `this.`. This denotes that it’s a member access. In the last line we construct an instance of the `Greeter` class using `new`. This calls into the constructor we defined earlier, creating a new object with the `Greeter` shape, and running the constructor to initialize it. ## Inheritance In TypeScript, we can use common object-oriented patterns. One of the most fundamental patterns in class-based programming is being able to extend existing classes to create new ones using inheritance. Let’s take a look at an example: class Animal { move(distanceInMeters: number = 0) { console.log(`Animal moved ${distanceInMeters}m.`); } }   class Dog extends Animal { bark() { console.log("Woof! Woof!"); } }   const dog = new Dog(); dog.bark(); dog.move(10); dog.bark(); This example shows the most basic inheritance feature: classes inherit properties and methods from base classes. Here, `Dog` is a _derived_ class that derives from the `Animal` _base_ class using the `extends` keyword. Derived classes are often called _subclasses_ , and base classes are often called _superclasses_. Because `Dog` extends the functionality from `Animal`, we were able to create an instance of `Dog` that could both `bark()` and `move()`. Let’s now look at a more complex example. class Animal { name: string; constructor(theName: string) { this.name = theName; } move(distanceInMeters: number = 0) { console.log(`${this.name} moved ${distanceInMeters}m.`); } }   class Snake extends Animal { constructor(name: string) { super(name); } move(distanceInMeters = 5) { console.log("Slithering..."); super.move(distanceInMeters); } }   class Horse extends Animal { constructor(name: string) { super(name); } move(distanceInMeters = 45) { console.log("Galloping..."); super.move(distanceInMeters); } }   let sam = new Snake("Sammy the Python"); let tom: Animal = new Horse("Tommy the Palomino");   sam.move(); tom.move(34); This example covers a few other features we didn’t previously mention. Again, we see the `extends` keywords used to create two new subclasses of `Animal`: `Horse` and `Snake`. One difference from the prior example is that each derived class that contains a constructor function _must_ call `super()` which will execute the constructor of the base class. What’s more, before we _ever_ access a property on `this` in a constructor body, we _have_ to call `super()`. This is an important rule that TypeScript will enforce. The example also shows how to override methods in the base class with methods that are specialized for the subclass. Here both `Snake` and `Horse` create a `move` method that overrides the `move` from `Animal`, giving it functionality specific to each class. Note that even though `tom` is declared as an `Animal`, since its value is a `Horse`, calling `tom.move(34)` will call the overriding method in `Horse`: Slithering... Sammy the Python moved 5m. Galloping... Tommy the Palomino moved 34m. ## Public, private, and protected modifiers ### Public by default In our examples, we’ve been able to freely access the members that we declared throughout our programs. If you’re familiar with classes in other languages, you may have noticed in the above examples we haven’t had to use the word `public` to accomplish this; for instance, C# requires that each member be explicitly labeled `public` to be visible. In TypeScript, each member is `public` by default. You may still mark a member `public` explicitly. We could have written the `Animal` class from the previous section in the following way: class Animal { public name: string;   public constructor(theName: string) { this.name = theName; }   public move(distanceInMeters: number) { console.log(`${this.name} moved ${distanceInMeters}m.`); } } ### ECMAScript Private Fields With TypeScript 3.8, TypeScript supports the new JavaScript syntax for private fields: class Animal { #name: string; constructor(theName: string) { this.#name = theName; } }   new Animal("Cat").#name; This syntax is built into the JavaScript runtime and can have better guarantees about the isolation of each private field. Right now, the best documentation for these private fields is in the TypeScript 3.8 [release notes](https://devblogs.microsoft.com/typescript/announcing- typescript-3-8-beta/#ecmascript-private-fields). ### Understanding TypeScript’s `private` TypeScript also has its own way to declare a member as being marked `private`, it cannot be accessed from outside of its containing class. For example: class Animal { private name: string;   constructor(theName: string) { this.name = theName; } }   new Animal("Cat").name; TypeScript is a structural type system. When we compare two different types, regardless of where they came from, if the types of all members are compatible, then we say the types themselves are compatible. However, when comparing types that have `private` and `protected` members, we treat these types differently. For two types to be considered compatible, if one of them has a `private` member, then the other must have a `private` member that originated in the same declaration. The same applies to `protected` members. Let’s look at an example to better see how this plays out in practice: class Animal { private name: string; constructor(theName: string) { this.name = theName; } }   class Rhino extends Animal { constructor() { super("Rhino"); } }   class Employee { private name: string; constructor(theName: string) { this.name = theName; } }   let animal = new Animal("Goat"); let rhino = new Rhino(); let employee = new Employee("Bob");   animal = rhino; animal = employee; In this example, we have an `Animal` and a `Rhino`, with `Rhino` being a subclass of `Animal`. We also have a new class `Employee` that looks identical to `Animal` in terms of shape. We create some instances of these classes and then try to assign them to each other to see what will happen. Because `Animal` and `Rhino` share the `private` side of their shape from the same declaration of `private name: string` in `Animal`, they are compatible. However, this is not the case for `Employee`. When we try to assign from an `Employee` to `Animal` we get an error that these types are not compatible. Even though `Employee` also has a `private` member called `name`, it’s not the one we declared in `Animal`. ### Understanding `protected` The `protected` modifier acts much like the `private` modifier with the exception that members declared `protected` can also be accessed within deriving classes. For example, class Person { protected name: string; constructor(name: string) { this.name = name; } }   class Employee extends Person { private department: string;   constructor(name: string, department: string) { super(name); this.department = department; }   public getElevatorPitch() { return `Hello, my name is ${this.name} and I work in ${this.department}.`; } }   let howard = new Employee("Howard", "Sales"); console.log(howard.getElevatorPitch()); console.log(howard.name); Notice that while we can’t use `name` from outside of `Person`, we can still use it from within an instance method of `Employee` because `Employee` derives from `Person`. A constructor may also be marked `protected`. This means that the class cannot be instantiated outside of its containing class, but can be extended. For example, class Person { protected name: string; protected constructor(theName: string) { this.name = theName; } }   // Employee can extend Person class Employee extends Person { private department: string;   constructor(name: string, department: string) { super(name); this.department = department; }   public getElevatorPitch() { return `Hello, my name is ${this.name} and I work in ${this.department}.`; } }   let howard = new Employee("Howard", "Sales"); let john = new Person("John"); ## Readonly modifier You can make properties readonly by using the `readonly` keyword. Readonly properties must be initialized at their declaration or in the constructor. class Octopus { readonly name: string; readonly numberOfLegs: number = 8;   constructor(theName: string) { this.name = theName; } }   let dad = new Octopus("Man with the 8 strong legs"); dad.name = "Man with the 3-piece suit"; ## Parameter properties In our last example, we had to declare a readonly member `name` and a constructor parameter `theName` in the `Octopus` class. This is needed in order to have the value of `theName` accessible after the `Octopus` constructor is executed. _Parameter properties_ let you create and initialize a member in one place. Here’s a further revision of the previous `Octopus` class using a parameter property: class Octopus { readonly numberOfLegs: number = 8; constructor(readonly name: string) {} }   let dad = new Octopus("Man with the 8 strong legs"); dad.name; Notice how we dropped `theName` altogether and just use the shortened `readonly name: string` parameter on the constructor to create and initialize the `name` member. We’ve consolidated the declarations and assignment into one location. Parameter properties are declared by prefixing a constructor parameter with an accessibility modifier or `readonly`, or both. Using `private` for a parameter property declares and initializes a private member; likewise, the same is done for `public`, `protected`, and `readonly`. ## Accessors TypeScript supports getters/setters as a way of intercepting accesses to a member of an object. This gives you a way of having finer-grained control over how a member is accessed on each object. Let’s convert a simple class to use `get` and `set`. First, let’s start with an example without getters and setters. class Employee { fullName: string; }   let employee = new Employee(); employee.fullName = "Bob Smith";   if (employee.fullName) { console.log(employee.fullName); } While allowing people to randomly set `fullName` directly is pretty handy, we may also want enforce some constraints when `fullName` is set. In this version, we add a setter that checks the length of the `newName` to make sure it’s compatible with the max-length of our backing database field. If it isn’t we throw an error notifying client code that something went wrong. To preserve existing functionality, we also add a simple getter that retrieves `fullName` unmodified. const fullNameMaxLength = 10;   class Employee { private _fullName: string = "";   get fullName(): string { return this._fullName; }   set fullName(newName: string) { if (newName && newName.length > fullNameMaxLength) { throw new Error("fullName has a max length of " + fullNameMaxLength); }   this._fullName = newName; } }   let employee = new Employee(); employee.fullName = "Bob Smith";   if (employee.fullName) { console.log(employee.fullName); } To prove to ourselves that our accessor is now checking the length of values, we can attempt to assign a name longer than 10 characters and verify that we get an error. A couple of things to note about accessors: First, accessors require you to set the compiler to output ECMAScript 5 or higher. Downleveling to ECMAScript 3 is not supported. Second, accessors with a `get` and no `set` are automatically inferred to be `readonly`. This is helpful when generating a `.d.ts` file from your code, because users of your property can see that they can’t change it. ## Static Properties Up to this point, we’ve only talked about the _instance_ members of the class, those that show up on the object when it’s instantiated. We can also create _static_ members of a class, those that are visible on the class itself rather than on the instances. In this example, we use `static` on the origin, as it’s a general value for all grids. Each instance accesses this value through prepending the name of the class. Similarly to prepending `this.` in front of instance accesses, here we prepend `Grid.` in front of static accesses. class Grid { static origin = { x: 0, y: 0 };   calculateDistanceFromOrigin(point: { x: number; y: number }) { let xDist = point.x - Grid.origin.x; let yDist = point.y - Grid.origin.y; return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale; }   constructor(public scale: number) {} }   let grid1 = new Grid(1.0); // 1x scale let grid2 = new Grid(5.0); // 5x scale   console.log(grid1.calculateDistanceFromOrigin({ x: 10, y: 10 })); console.log(grid2.calculateDistanceFromOrigin({ x: 10, y: 10 })); ## Abstract Classes Abstract classes are base classes from which other classes may be derived. They may not be instantiated directly. Unlike an interface, an abstract class may contain implementation details for its members. The `abstract` keyword is used to define abstract classes as well as abstract methods within an abstract class. abstract class Animal { abstract makeSound(): void;   move(): void { console.log("roaming the earth..."); } } Methods within an abstract class that are marked as abstract do not contain an implementation and must be implemented in derived classes. Abstract methods share a similar syntax to interface methods. Both define the signature of a method without including a method body. However, abstract methods must include the `abstract` keyword and may optionally include access modifiers. abstract class Department { constructor(public name: string) {}   printName(): void { console.log("Department name: " + this.name); }   abstract printMeeting(): void; // must be implemented in derived classes }   class AccountingDepartment extends Department { constructor() { super("Accounting and Auditing"); // constructors in derived classes must call super() }   printMeeting(): void { console.log("The Accounting Department meets each Monday at 10am."); }   generateReports(): void { console.log("Generating accounting reports..."); } }   let department: Department; // ok to create a reference to an abstract type department = new Department(); // error: cannot create an instance of an abstract class department = new AccountingDepartment(); // ok to create and assign a non-abstract subclass department.printName(); department.printMeeting(); department.generateReports(); // error: department is not of type AccountingDepartment, cannot access generateReports ## Advanced Techniques ## Constructor functions When you declare a class in TypeScript, you are actually creating multiple declarations at the same time. The first is the type of the _instance_ of the class. class Greeter { greeting: string;   constructor(message: string) { this.greeting = message; }   greet() { return "Hello, " + this.greeting; } }   let greeter: Greeter; greeter = new Greeter("world"); console.log(greeter.greet()); // "Hello, world" Here, when we say `let greeter: Greeter`, we’re using `Greeter` as the type of instances of the class `Greeter`. This is almost second nature to programmers from other object-oriented languages. We’re also creating another value that we call the _constructor function_. This is the function that is called when we `new` up instances of the class. To see what this looks like in practice, let’s take a look at the JavaScript created by the above example: let Greeter = (function () { function Greeter(message) { this.greeting = message; }   Greeter.prototype.greet = function () { return "Hello, " + this.greeting; };   return Greeter; })();   let greeter; greeter = new Greeter("world"); console.log(greeter.greet()); // "Hello, world" Here, `let Greeter` is going to be assigned the constructor function. When we call `new` and run this function, we get an instance of the class. The constructor function also contains all of the static members of the class. Another way to think of each class is that there is an _instance_ side and a _static_ side. Let’s modify the example a bit to show this difference: class Greeter { static standardGreeting = "Hello, there"; greeting: string; greet() { if (this.greeting) { return "Hello, " + this.greeting; } else { return Greeter.standardGreeting; } } }   let greeter1: Greeter; greeter1 = new Greeter(); console.log(greeter1.greet()); // "Hello, there"   let greeterMaker: typeof Greeter = Greeter; greeterMaker.standardGreeting = "Hey there!";   let greeter2: Greeter = new greeterMaker(); console.log(greeter2.greet()); // "Hey there!"   let greeter3: Greeter; greeter3 = new Greeter(); console.log(greeter3.greet()); // "Hey there!" In this example, `greeter1` works similarly to before. We instantiate the `Greeter` class, and use this object. This we have seen before. Next, we then use the class directly. Here we create a new variable called `greeterMaker`. This variable will hold the class itself, or said another way its constructor function. Here we use `typeof Greeter`, that is “give me the type of the `Greeter` class itself” rather than the instance type. Or, more precisely, “give me the type of the symbol called `Greeter`,” which is the type of the constructor function. This type will contain all of the static members of Greeter along with the constructor that creates instances of the `Greeter` class. We show this by using `new` on `greeterMaker`, creating new instances of `Greeter` and invoking them as before. It is also good to mention that changing static property is frowned upon, here `greeter3` has `"Hey there!"` instead of `"Hello, there"` on `standardGreeting`. ## Using a class as an interface As we said in the previous section, a class declaration creates two things: a type representing instances of the class and a constructor function. Because classes create types, you can use them in the same places you would be able to use interfaces. class Point { x: number; y: number; }   interface Point3d extends Point { z: number; }   let point3d: Point3d = { x: 1, y: 2, z: 3 }; ##### On this page * Classes * Inheritance * Public, private, and protected modifiers * Public by default * ECMAScript Private Fields * Understanding TypeScript’s private * Understanding protected * Readonly modifier * Parameter properties * Accessors * Static Properties * Abstract Classes * Advanced Techniques * Constructor functions * Using a class as an interface ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v1/Classes.md) ❤ Contributors to this page: RC DR OT NS BW 25+ Last updated: Mar 11, 2025 # Compiler Options in MSBuild Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) # Compiler Options in MSBuild ## Overview When you have an MSBuild based project which utilizes TypeScript such as an ASP.NET Core project, you can configure TypeScript in two ways. Either via a `tsconfig.json` or via the project settings. ## Using a `tsconfig.json` We recommend using a `tsconfig.json` for your project when possible. To add one to an existing project, add a new item to your project which is called a “TypeScript JSON Configuration File” in modern versions of Visual Studio. The new `tsconfig.json` will then be used as the source of truth for TypeScript-specific build information like files and configuration. You can learn [about how TSConfigs works here](tsconfig-json) and there is a [comprehensive reference here](../../tsconfig). ## Using Project Settings You can also define the configuration for TypeScript inside you project’s settings. This is done by editing the XML in your `.csproj` to define `PropertyGroups` which describe how the build can work: true true There is a series of mappings for common TypeScript settings, these are settings which map directly to [TypeScript cli options](compiler-options) and are used to help you write a more understandable project file. You can use the [TSConfig reference](../../tsconfig) to get more information on what values and defaults are for each mapping. ### CLI Mappings MSBuild Config Name | TSC Flag ---|--- `` | `[--allowJs](../../tsconfig/index#allowJs)` Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. `` | `[--removeComments](../../tsconfig/index#removeComments)` Disable emitting comments. `` | `[--noImplicitAny](../../tsconfig/index#noImplicitAny)` Enable error reporting for expressions and declarations with an implied `any` type.. `` | `[--declaration](../../tsconfig/index#declaration)` Generate .d.ts files from TypeScript and JavaScript files in your project. `` | `[--module](../../tsconfig/index#module)` Specify what module code is generated. `` | `[--jsx](../../tsconfig/index#jsx)` Specify what JSX code is generated. `` | `[--outDir](../../tsconfig/index#outDir)` Specify an output folder for all emitted files. `` | `[--sourcemap](../../tsconfig/index#sourcemap)` Create source map files for emitted JavaScript files. `` | `[--target](../../tsconfig/index#target)` Set the JavaScript language version for emitted JavaScript and include compatible library declarations. `` | `[--noResolve](../../tsconfig/index#noResolve)` Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. `` | `[--mapRoot](../../tsconfig/index#mapRoot)` Specify the location where debugger should locate map files instead of generated locations. `` | `[--sourceRoot](../../tsconfig/index#sourceRoot)` Specify the root path for debuggers to find the reference source code. `` | `[--charset](../../tsconfig/index#charset)` No longer supported. In early versions, manually set the text encoding for reading files. `` | `[--emitBOM](../../tsconfig/index#emitBOM)` Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. `` | `[--noLib](../../tsconfig/index#noLib)` Disable including any library files, including the default lib.d.ts. `` | `[--preserveConstEnums](../../tsconfig/index#preserveConstEnums)` Disable erasing `const enum` declarations in generated code. `` | `[--suppressImplicitAnyIndexErrors](../../tsconfig/index#suppressImplicitAnyIndexErrors)` Suppress `noImplicitAny` errors when indexing objects that lack index signatures. `` | `[--noEmitHelpers](../../tsconfig/index#noEmitHelpers)` Disable generating custom helper functions like `__extends` in compiled output. `` | `[--inlineSourceMap](../../tsconfig/index#inlineSourceMap)` Include sourcemap files inside the emitted JavaScript. `` | `[--inlineSources](../../tsconfig/index#inlineSources)` Include source code in the sourcemaps inside the emitted JavaScript. `` | `[--newLine](../../tsconfig/index#newLine)` Set the newline character for emitting files. `` | `[--isolatedModules](../../tsconfig/index#isolatedModules)` Ensure that each file can be safely transpiled without relying on other imports. `` | `[--emitDecoratorMetadata](../../tsconfig/index#emitDecoratorMetadata)` Emit design-type metadata for decorated declarations in source files. `` | `[--rootDir](../../tsconfig/index#rootDir)` Specify the root folder within your source files. `` | `[--experimentalDecorators](../../tsconfig/index#experimentalDecorators)` Enable experimental support for TC39 stage 2 draft decorators. `` | `[--moduleResolution](../../tsconfig/index#moduleResolution)` Specify how TypeScript looks up a file from a given module specifier. `` | `[--suppressExcessPropertyErrors](../../tsconfig/index#suppressExcessPropertyErrors)` Disable reporting of excess property errors during the creation of object literals. `` | `[--reactNamespace](../../tsconfig/index#reactNamespace)` Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. `` | `[--skipDefaultLibCheck](../../tsconfig/index#skipDefaultLibCheck)` Skip type checking .d.ts files that are included with TypeScript. `` | `[--allowUnusedLabels](../../tsconfig/index#allowUnusedLabels)` Disable error reporting for unused labels. `` | `[--noImplicitReturns](../../tsconfig/index#noImplicitReturns)` Enable error reporting for codepaths that do not explicitly return in a function. `` | `[--noFallthroughCasesInSwitch](../../tsconfig/index#noFallthroughCasesInSwitch)` Enable error reporting for fallthrough cases in switch statements. `` | `[--allowUnreachableCode](../../tsconfig/index#allowUnreachableCode)` Disable error reporting for unreachable code. `` | `[--forceConsistentCasingInFileNames](../../tsconfig/index#forceConsistentCasingInFileNames)` Ensure that casing is correct in imports. `` | `[--allowSyntheticDefaultImports](../../tsconfig/index#allowSyntheticDefaultImports)` Allow 'import x from y' when a module doesn't have a default export. `` | `[--noImplicitUseStrict](../../tsconfig/index#noImplicitUseStrict)` Disable adding 'use strict' directives in emitted JavaScript files. `` | `[--lib](../../tsconfig/index#lib)` Specify a set of bundled library declaration files that describe the target runtime environment. `` | `[--baseUrl](../../tsconfig/index#baseUrl)` Specify the base directory to resolve bare specifier module names. `` | `[--declarationDir](../../tsconfig/index#declarationDir)` Specify the output directory for generated declaration files. `` | `[--noImplicitThis](../../tsconfig/index#noImplicitThis)` Enable error reporting when `this` is given the type `any`. `` | `[--skipLibCheck](../../tsconfig/index#skipLibCheck)` Skip type checking all .d.ts files. `` | `[--strictNullChecks](../../tsconfig/index#strictNullChecks)` When type checking, take into account `null` and `undefined`. `` | `[--noUnusedLocals](../../tsconfig/index#noUnusedLocals)` Enable error reporting when a local variables aren't read. `` | `[--noUnusedParameters](../../tsconfig/index#noUnusedParameters)` Raise an error when a function parameter isn't read `` | `[--alwaysStrict](../../tsconfig/index#alwaysStrict)` Ensure 'use strict' is always emitted. `` | `[--importHelpers](../../tsconfig/index#importHelpers)` Allow importing helper functions from tslib once per project, instead of including them per-file. `` | `[--jsxFactory](../../tsconfig/index#jsxFactory)` Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' `` | `[--stripInternal](../../tsconfig/index#stripInternal)` Disable emitting declarations that have `@internal` in their JSDoc comments. `` | `[--checkJs](../../tsconfig/index#checkJs)` Enable error reporting in type-checked JavaScript files. `` | `[--downlevelIteration](../../tsconfig/index#downlevelIteration)` Emit more compliant, but verbose and less performant JavaScript for iteration. `` | `[--strict](../../tsconfig/index#strict)` Enable all strict type checking options. `` | `[--noStrictGenericChecks](../../tsconfig/index#noStrictGenericChecks)` Disable strict checking of generic signatures in function types. `` | `[--preserveSymlinks](../../tsconfig/index#preserveSymlinks)` Disable resolving symlinks to their realpath. This correlates to the same flag in node. `` | `[--strictFunctionTypes](../../tsconfig/index#strictFunctionTypes)` When assigning functions, check to ensure parameters and the return values are subtype-compatible. `` | `[--strictPropertyInitialization](../../tsconfig/index#strictPropertyInitialization)` Check for class properties that are declared but not set in the constructor. `` | `[--esModuleInterop](../../tsconfig/index#esModuleInterop)` Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. `` | `[--emitDeclarationOnly](../../tsconfig/index#emitDeclarationOnly)` Only output d.ts files and not JavaScript files. `` | `[--keyofStringsOnly](../../tsconfig/index#keyofStringsOnly)` Make keyof only return strings instead of string, numbers or symbols. Legacy option. `` | `[--useDefineForClassFields](../../tsconfig/index#useDefineForClassFields)` Emit ECMAScript-standard-compliant class fields. `` | `[--declarationMap](../../tsconfig/index#declarationMap)` Create sourcemaps for d.ts files. `` | `[--resolveJsonModule](../../tsconfig/index#resolveJsonModule)` Enable importing .json files `` | `[--strictBindCallApply](../../tsconfig/index#strictBindCallApply)` Check that the arguments for `bind`, `call`, and `apply` methods match the original function. `` | `[--noEmitOnError](../../tsconfig/index#noEmitOnError)` Disable emitting files if any type checking errors are reported. ### Additional Flags Because the MSBuild system passes arguments directly to the TypeScript CLI, you can use the option `TypeScriptAdditionalFlags` to provide specific flags which don’t have a mapping above. For example, this would turn on [`noPropertyAccessFromIndexSignature`](../../tsconfig#noPropertyAccessFromIndexSignature): $(TypeScriptAdditionalFlags) --noPropertyAccessFromIndexSignature ### Debug and Release Builds You can use PropertyGroup conditions to define different sets of configurations. For example, a common task is stripping comments and sourcemaps in production. In this example, we define a debug and release property group which have different TypeScript configurations: false true true false ### ToolsVersion The value of `1.7` property in the project file identifies the compiler version to use to build (1.7 in this example). This allows a project to build against the same versions of the compiler on different machines. If `TypeScriptToolsVersion` is not specified, the latest compiler version installed on the machine will be used to build. Users using newer versions of TS, will see a prompt to upgrade their project on first load. ### TypeScriptCompileBlocked If you are using a different build tool to build your project (e.g. gulp, grunt , etc.) and VS for the development and debugging experience, set `true` in your project. This should give you all the editing support, but not the build when you hit F5. ### TypeScriptEnableIncrementalMSBuild (TypeScript 4.2 Beta and later) By default, MSBuild will attempt to only run the TypeScript compiler when the project’s source files have been updated since the last compilation. However, if this behavior is causing issues, such as when TypeScript’s [`incremental`](../../tsconfig#incremental) option is enabled, set `false` to ensure the TypeScript compiler is invoked with every run of MSBuild. ##### On this page * Overview * Using a tsconfig.json * Using Project Settings * Additional Flags * Debug and Release Builds * ToolsVersion * TypeScriptCompileBlocked * TypeScriptEnableIncrementalMSBuild (TypeScript 4.2 Beta and later) ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/project- config/Compiler%20Options%20in%20MSBuild.md) ❤ Contributors to this page: MH OT Y DR BL 13+ Last updated: Mar 11, 2025 # tsc CLI Options Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) # tsc CLI Options ## Using the CLI Running `tsc` locally will compile the closest project defined by a `tsconfig.json`, or you can compile a set of TypeScript files by passing in a glob of files you want. When input files are specified on the command line, `tsconfig.json` files are ignored. # Run a compile based on a backwards look through the fs for a tsconfig.json tsc # Emit JS for just the index.ts with the compiler defaults tsc index.ts # Emit JS for any .ts files in the folder src, with the default settings tsc src/*.ts # Emit files referenced in with the compiler settings from tsconfig.production.json tsc --project tsconfig.production.json # Emit d.ts files for a js file with showing compiler options which are booleans tsc index.js --declaration --emitDeclarationOnly # Emit a single .js file from two files via compiler options which take string arguments tsc app.ts util.ts --target esnext --outfile index.js ## Compiler Options **If you’re looking for more information about the compiler options in a tsconfig, check out the[TSConfig Reference](../../tsconfig)** ### CLI Commands Flag | Type ---|--- `--all` | `boolean` Show all compiler options. `--help` | `boolean` Gives local information for help on the CLI. `--init` | `boolean` Initializes a TypeScript project and creates a tsconfig.json file. `--listFilesOnly` | `boolean` Print names of files that are part of the compilation and then stop processing. `--locale` | `string` Set the language of the messaging from TypeScript. This does not affect emit. `--project` | `string` Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'. `--showConfig` | `boolean` Print the final configuration instead of building. `--version` | `boolean` Print the compiler's version. ### Build Options Flag | Type ---|--- `--build` | `boolean` Build one or more projects and their dependencies, if out of date `--clean` | `boolean` Delete the outputs of all projects. `--dry` | `boolean` Show what would be built (or deleted, if specified with '--clean') `[--force](../../tsconfig/index#force)` | `boolean` Build all projects, including those that appear to be up to date. `[--verbose](../../tsconfig/index#verbose)` | `boolean` Enable verbose logging. ### Watch Options Flag | Type ---|--- `[--excludeDirectories](../../tsconfig/index#excludeDirectories)` | `list` Remove a list of directories from the watch process. `[--excludeFiles](../../tsconfig/index#excludeFiles)` | `list` Remove a list of files from the watch mode's processing. `[--fallbackPolling](../../tsconfig/index#fallbackPolling)` | `fixedinterval`, `priorityinterval`, `dynamicpriority`, or `fixedchunksize` Specify what approach the watcher should use if the system runs out of native file watchers. `[--synchronousWatchDirectory](../../tsconfig/index#synchronousWatchDirectory)` | `boolean` Synchronously call callbacks and update the state of directory watchers on platforms that don`t support recursive watching natively. `--watch` | `boolean` Watch input files. `[--watchDirectory](../../tsconfig/index#watchDirectory)` | `usefsevents`, `fixedpollinginterval`, `dynamicprioritypolling`, or `fixedchunksizepolling` Specify how directories are watched on systems that lack recursive file- watching functionality. `[--watchFile](../../tsconfig/index#watchFile)` | `fixedpollinginterval`, `prioritypollinginterval`, `dynamicprioritypolling`, `fixedchunksizepolling`, `usefsevents`, or `usefseventsonparentdirectory` Specify how the TypeScript watch mode works. ### Compiler Flags Flag | Type | Default ---|---|--- `[--allowArbitraryExtensions](../../tsconfig/index#allowArbitraryExtensions)` | `boolean` | `false` Enable importing files with any extension, provided a declaration file is present. `[--allowImportingTsExtensions](../../tsconfig/index#allowImportingTsExtensions)` | `boolean` | `true` if `rewriteRelativeImportExtensions`; `false` otherwise. Allow imports to include TypeScript file extensions. `[--allowJs](../../tsconfig/index#allowJs)` | `boolean` | `false` Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. `[--allowSyntheticDefaultImports](../../tsconfig/index#allowSyntheticDefaultImports)` | `boolean` | `true` if `esModuleInterop` is enabled, `module` is `system`, or `moduleResolution` is `bundler`; `false` otherwise. Allow 'import x from y' when a module doesn't have a default export. `[--allowUmdGlobalAccess](../../tsconfig/index#allowUmdGlobalAccess)` | `boolean` | `false` Allow accessing UMD globals from modules. `[--allowUnreachableCode](../../tsconfig/index#allowUnreachableCode)` | `boolean` | Disable error reporting for unreachable code. `[--allowUnusedLabels](../../tsconfig/index#allowUnusedLabels)` | `boolean` | Disable error reporting for unused labels. `[--alwaysStrict](../../tsconfig/index#alwaysStrict)` | `boolean` | `true` if `strict`; `false` otherwise. Ensure 'use strict' is always emitted. `[--assumeChangesOnlyAffectDirectDependencies](../../tsconfig/index#assumeChangesOnlyAffectDirectDependencies)` | `boolean` | `false` Have recompiles in projects that use `incremental` and `watch` mode assume that changes within a file will only affect files directly depending on it. `[--baseUrl](../../tsconfig/index#baseUrl)` | `string` | Specify the base directory to resolve bare specifier module names. `[--charset](../../tsconfig/index#charset)` | `string` | `utf8` No longer supported. In early versions, manually set the text encoding for reading files. `[--checkJs](../../tsconfig/index#checkJs)` | `boolean` | `false` Enable error reporting in type-checked JavaScript files. `[--composite](../../tsconfig/index#composite)` | `boolean` | `false` Enable constraints that allow a TypeScript project to be used with project references. `[--customConditions](../../tsconfig/index#customConditions)` | `list` | Conditions to set in addition to the resolver-specific defaults when resolving imports. `[--declaration](../../tsconfig/index#declaration)` | `boolean` | `true` if `composite`; `false` otherwise. Generate .d.ts files from TypeScript and JavaScript files in your project. `[--declarationDir](../../tsconfig/index#declarationDir)` | `string` | Specify the output directory for generated declaration files. `[--declarationMap](../../tsconfig/index#declarationMap)` | `boolean` | `false` Create sourcemaps for d.ts files. `[--diagnostics](../../tsconfig/index#diagnostics)` | `boolean` | `false` Output compiler performance information after building. `[--disableReferencedProjectLoad](../../tsconfig/index#disableReferencedProjectLoad)` | `boolean` | `false` Reduce the number of projects loaded automatically by TypeScript. `[--disableSizeLimit](../../tsconfig/index#disableSizeLimit)` | `boolean` | `false` Remove the 20mb cap on total source code size for JavaScript files in the TypeScript language server. `[--disableSolutionSearching](../../tsconfig/index#disableSolutionSearching)` | `boolean` | `false` Opt a project out of multi-project reference checking when editing. `[--disableSourceOfProjectReferenceRedirect](../../tsconfig/index#disableSourceOfProjectReferenceRedirect)` | `boolean` | `false` Disable preferring source files instead of declaration files when referencing composite projects. `[--downlevelIteration](../../tsconfig/index#downlevelIteration)` | `boolean` | `false` Emit more compliant, but verbose and less performant JavaScript for iteration. `[--emitBOM](../../tsconfig/index#emitBOM)` | `boolean` | `false` Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. `[--emitDeclarationOnly](../../tsconfig/index#emitDeclarationOnly)` | `boolean` | `false` Only output d.ts files and not JavaScript files. `[--emitDecoratorMetadata](../../tsconfig/index#emitDecoratorMetadata)` | `boolean` | `false` Emit design-type metadata for decorated declarations in source files. `[--erasableSyntaxOnly](../../tsconfig/index#erasableSyntaxOnly)` | `boolean` | `false` Do not allow runtime constructs that are not part of ECMAScript. `[--esModuleInterop](../../tsconfig/index#esModuleInterop)` | `boolean` | `true` if `module` is `node16`, `nodenext`, or `preserve`; `false` otherwise. Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. `[--exactOptionalPropertyTypes](../../tsconfig/index#exactOptionalPropertyTypes)` | `boolean` | `false` Interpret optional property types as written, rather than adding `undefined`. `[--experimentalDecorators](../../tsconfig/index#experimentalDecorators)` | `boolean` | `false` Enable experimental support for TC39 stage 2 draft decorators. `[--explainFiles](../../tsconfig/index#explainFiles)` | `boolean` | `false` Print files read during the compilation including why it was included. `[--extendedDiagnostics](../../tsconfig/index#extendedDiagnostics)` | `boolean` | `false` Output more detailed compiler performance information after building. `[--forceConsistentCasingInFileNames](../../tsconfig/index#forceConsistentCasingInFileNames)` | `boolean` | `true` Ensure that casing is correct in imports. `[--generateCpuProfile](../../tsconfig/index#generateCpuProfile)` | `string` | `profile.cpuprofile` Emit a v8 CPU profile of the compiler run for debugging. `[--generateTrace](../../tsconfig/index#generateTrace)` | `string` | Generates an event trace and a list of types. `[--importHelpers](../../tsconfig/index#importHelpers)` | `boolean` | `false` Allow importing helper functions from tslib once per project, instead of including them per-file. `[--importsNotUsedAsValues](../../tsconfig/index#importsNotUsedAsValues)` | `remove`, `preserve`, or `error` | `remove` Specify emit/checking behavior for imports that are only used for types. `[--incremental](../../tsconfig/index#incremental)` | `boolean` | `true` if `composite`; `false` otherwise. Save .tsbuildinfo files to allow for incremental compilation of projects. `[--inlineSourceMap](../../tsconfig/index#inlineSourceMap)` | `boolean` | `false` Include sourcemap files inside the emitted JavaScript. `[--inlineSources](../../tsconfig/index#inlineSources)` | `boolean` | `false` Include source code in the sourcemaps inside the emitted JavaScript. `[--isolatedDeclarations](../../tsconfig/index#isolatedDeclarations)` | `boolean` | `false` Require sufficient annotation on exports so other tools can trivially generate declaration files. `[--isolatedModules](../../tsconfig/index#isolatedModules)` | `boolean` | `true` if `verbatimModuleSyntax`; `false` otherwise. Ensure that each file can be safely transpiled without relying on other imports. `[--jsx](../../tsconfig/index#jsx)` | `preserve`, `react`, `react-native`, `react-jsx`, or `react-jsxdev` | Specify what JSX code is generated. `[--jsxFactory](../../tsconfig/index#jsxFactory)` | `string` | `React.createElement` Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. `[--jsxFragmentFactory](../../tsconfig/index#jsxFragmentFactory)` | `string` | `React.Fragment` Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. `[--jsxImportSource](../../tsconfig/index#jsxImportSource)` | `string` | `react` Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`. `[--keyofStringsOnly](../../tsconfig/index#keyofStringsOnly)` | `boolean` | `false` Make keyof only return strings instead of string, numbers or symbols. Legacy option. `[--lib](../../tsconfig/index#lib)` | `list` | Specify a set of bundled library declaration files that describe the target runtime environment. `[--libReplacement](../../tsconfig/index#libReplacement)` | `boolean` | `true` Enable substitution of default `lib` files with custom ones. `[--listEmittedFiles](../../tsconfig/index#listEmittedFiles)` | `boolean` | `false` Print the names of emitted files after a compilation. `[--listFiles](../../tsconfig/index#listFiles)` | `boolean` | `false` Print all of the files read during the compilation. `[--mapRoot](../../tsconfig/index#mapRoot)` | `string` | Specify the location where debugger should locate map files instead of generated locations. `[--maxNodeModuleJsDepth](../../tsconfig/index#maxNodeModuleJsDepth)` | `number` | `0` Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. `[--module](../../tsconfig/index#module)` | `none`, `commonjs`, `amd`, `umd`, `system`, `es6`/`es2015`, `es2020`, `es2022`, `esnext`, `node16`, `node18`, `nodenext`, or `preserve` | `CommonJS` if `target` is `ES5`; `ES6`/`ES2015` otherwise. Specify what module code is generated. `[--moduleDetection](../../tsconfig/index#moduleDetection)` | `legacy`, `auto`, or `force` | "auto": Treat files with imports, exports, import.meta, jsx (with jsx: react-jsx), or esm format (with module: node16+) as modules. Specify what method is used to detect whether a file is a script or a module. `[--moduleResolution](../../tsconfig/index#moduleResolution)` | `classic`, `node10`/`node`, `node16`, `nodenext`, or `bundler` | `Node10` if `module` is `CommonJS`; `Node16` if `module` is `Node16` or `Node18`; `NodeNext` if `module` is `NodeNext`; `Bundler` if `module` is `Preserve`; `Classic` otherwise. Specify how TypeScript looks up a file from a given module specifier. `[--moduleSuffixes](../../tsconfig/index#moduleSuffixes)` | `list` | List of file name suffixes to search when resolving a module. `[--newLine](../../tsconfig/index#newLine)` | `crlf` or `lf` | `lf` Set the newline character for emitting files. `[--noCheck](../../tsconfig/index#noCheck)` | `boolean` | `false` Disable full type checking (only critical parse and emit errors will be reported). `[--noEmit](../../tsconfig/index#noEmit)` | `boolean` | `false` Disable emitting files from a compilation. `[--noEmitHelpers](../../tsconfig/index#noEmitHelpers)` | `boolean` | `false` Disable generating custom helper functions like `__extends` in compiled output. `[--noEmitOnError](../../tsconfig/index#noEmitOnError)` | `boolean` | `false` Disable emitting files if any type checking errors are reported. `[--noErrorTruncation](../../tsconfig/index#noErrorTruncation)` | `boolean` | `false` Disable truncating types in error messages. `[--noFallthroughCasesInSwitch](../../tsconfig/index#noFallthroughCasesInSwitch)` | `boolean` | `false` Enable error reporting for fallthrough cases in switch statements. `[--noImplicitAny](../../tsconfig/index#noImplicitAny)` | `boolean` | `true` if `strict`; `false` otherwise. Enable error reporting for expressions and declarations with an implied `any` type. `[--noImplicitOverride](../../tsconfig/index#noImplicitOverride)` | `boolean` | `false` Ensure overriding members in derived classes are marked with an override modifier. `[--noImplicitReturns](../../tsconfig/index#noImplicitReturns)` | `boolean` | `false` Enable error reporting for codepaths that do not explicitly return in a function. `[--noImplicitThis](../../tsconfig/index#noImplicitThis)` | `boolean` | `true` if `strict`; `false` otherwise. Enable error reporting when `this` is given the type `any`. `[--noImplicitUseStrict](../../tsconfig/index#noImplicitUseStrict)` | `boolean` | `false` Disable adding 'use strict' directives in emitted JavaScript files. `[--noLib](../../tsconfig/index#noLib)` | `boolean` | `false` Disable including any library files, including the default lib.d.ts. `[--noPropertyAccessFromIndexSignature](../../tsconfig/index#noPropertyAccessFromIndexSignature)` | `boolean` | `false` Enforces using indexed accessors for keys declared using an indexed type. `[--noResolve](../../tsconfig/index#noResolve)` | `boolean` | `false` Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. `[--noStrictGenericChecks](../../tsconfig/index#noStrictGenericChecks)` | `boolean` | `false` Disable strict checking of generic signatures in function types. `[--noUncheckedIndexedAccess](../../tsconfig/index#noUncheckedIndexedAccess)` | `boolean` | `false` Add `undefined` to a type when accessed using an index. `[--noUncheckedSideEffectImports](../../tsconfig/index#noUncheckedSideEffectImports)` | `boolean` | `false` Check side effect imports. `[--noUnusedLocals](../../tsconfig/index#noUnusedLocals)` | `boolean` | `false` Enable error reporting when local variables aren't read. `[--noUnusedParameters](../../tsconfig/index#noUnusedParameters)` | `boolean` | `false` Raise an error when a function parameter isn't read. `[--out](../../tsconfig/index#out)` | `string` | Deprecated setting. Use `outFile` instead. `[--outDir](../../tsconfig/index#outDir)` | `string` | Specify an output folder for all emitted files. `[--outFile](../../tsconfig/index#outFile)` | `string` | Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. `[--paths](../../tsconfig/index#paths)` | `object` | Specify a set of entries that re-map imports to additional lookup locations. `[--plugins](../../tsconfig/index#plugins)` | `list` | Specify a list of language service plugins to include. `[--preserveConstEnums](../../tsconfig/index#preserveConstEnums)` | `boolean` | `true` if `isolatedModules`; `false` otherwise. Disable erasing `const enum` declarations in generated code. `[--preserveSymlinks](../../tsconfig/index#preserveSymlinks)` | `boolean` | `false` Disable resolving symlinks to their realpath. This correlates to the same flag in node. `[--preserveValueImports](../../tsconfig/index#preserveValueImports)` | `boolean` | `false` Preserve unused imported values in the JavaScript output that would otherwise be removed. `[--preserveWatchOutput](../../tsconfig/index#preserveWatchOutput)` | `boolean` | `false` Disable wiping the console in watch mode. `[--pretty](../../tsconfig/index#pretty)` | `boolean` | `true` Enable color and formatting in TypeScript's output to make compiler errors easier to read. `[--reactNamespace](../../tsconfig/index#reactNamespace)` | `string` | `React` Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. `[--removeComments](../../tsconfig/index#removeComments)` | `boolean` | `false` Disable emitting comments. `[--resolveJsonModule](../../tsconfig/index#resolveJsonModule)` | `boolean` | `false` Enable importing .json files. `[--resolvePackageJsonExports](../../tsconfig/index#resolvePackageJsonExports)` | `boolean` | `true` when `moduleResolution` is `node16`, `nodenext`, or `bundler`; otherwise `false` Use the package.json 'exports' field when resolving package imports. `[--resolvePackageJsonImports](../../tsconfig/index#resolvePackageJsonImports)` | `boolean` | `true` when `moduleResolution` is `node16`, `nodenext`, or `bundler`; otherwise `false` Use the package.json 'imports' field when resolving imports. `[--rewriteRelativeImportExtensions](../../tsconfig/index#rewriteRelativeImportExtensions)` | `boolean` | `false` Does something `[--rootDir](../../tsconfig/index#rootDir)` | `string` | Computed from the list of input files. Specify the root folder within your source files. `[--rootDirs](../../tsconfig/index#rootDirs)` | `list` | Computed from the list of input files. Allow multiple folders to be treated as one when resolving modules. `[--skipDefaultLibCheck](../../tsconfig/index#skipDefaultLibCheck)` | `boolean` | `false` Skip type checking .d.ts files that are included with TypeScript. `[--skipLibCheck](../../tsconfig/index#skipLibCheck)` | `boolean` | `false` Skip type checking all .d.ts files. `[--sourceMap](../../tsconfig/index#sourceMap)` | `boolean` | `false` Create source map files for emitted JavaScript files. `[--sourceRoot](../../tsconfig/index#sourceRoot)` | `string` | Specify the root path for debuggers to find the reference source code. `[--stopBuildOnErrors](../../tsconfig/index#stopBuildOnErrors)` | `boolean` | Skip building downstream projects on error in upstream project. `[--strict](../../tsconfig/index#strict)` | `boolean` | `false` Enable all strict type-checking options. `[--strictBindCallApply](../../tsconfig/index#strictBindCallApply)` | `boolean` | `true` if `strict`; `false` otherwise. Check that the arguments for `bind`, `call`, and `apply` methods match the original function. `[--strictBuiltinIteratorReturn](../../tsconfig/index#strictBuiltinIteratorReturn)` | `boolean` | `true` if `strict`; `false` otherwise. Built-in iterators are instantiated with a TReturn type of undefined instead of any. `[--strictFunctionTypes](../../tsconfig/index#strictFunctionTypes)` | `boolean` | `true` if `strict`; `false` otherwise. When assigning functions, check to ensure parameters and the return values are subtype-compatible. `[--strictNullChecks](../../tsconfig/index#strictNullChecks)` | `boolean` | `true` if `strict`; `false` otherwise. When type checking, take into account `null` and `undefined`. `[--strictPropertyInitialization](../../tsconfig/index#strictPropertyInitialization)` | `boolean` | `true` if `strict`; `false` otherwise. Check for class properties that are declared but not set in the constructor. `[--stripInternal](../../tsconfig/index#stripInternal)` | `boolean` | `false` Disable emitting declarations that have `@internal` in their JSDoc comments. `[--suppressExcessPropertyErrors](../../tsconfig/index#suppressExcessPropertyErrors)` | `boolean` | `false` Disable reporting of excess property errors during the creation of object literals. `[--suppressImplicitAnyIndexErrors](../../tsconfig/index#suppressImplicitAnyIndexErrors)` | `boolean` | `false` Suppress `noImplicitAny` errors when indexing objects that lack index signatures. `[--target](../../tsconfig/index#target)` | `es3`, `es5`, `es6`/`es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020`, `es2021`, `es2022`, `es2023`, `es2024`, or `esnext` | `ES5` Set the JavaScript language version for emitted JavaScript and include compatible library declarations. `[--traceResolution](../../tsconfig/index#traceResolution)` | `boolean` | `false` Log paths used during the `moduleResolution` process. `[--tsBuildInfoFile](../../tsconfig/index#tsBuildInfoFile)` | `string` | `.tsbuildinfo` The file to store `.tsbuildinfo` incremental build information in. `[--typeRoots](../../tsconfig/index#typeRoots)` | `list` | Specify multiple folders that act like `./node_modules/@types`. `[--types](../../tsconfig/index#types)` | `list` | Specify type package names to be included without being referenced in a source file. `[--useDefineForClassFields](../../tsconfig/index#useDefineForClassFields)` | `boolean` | `true` if `target` is `ES2022` or higher, including `ESNext`; `false` otherwise. Emit ECMAScript-standard-compliant class fields. `[--useUnknownInCatchVariables](../../tsconfig/index#useUnknownInCatchVariables)` | `boolean` | `true` if `strict`; `false` otherwise. Default catch clause variables as `unknown` instead of `any`. `[--verbatimModuleSyntax](../../tsconfig/index#verbatimModuleSyntax)` | `boolean` | `false` Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. ## Related * Every option is fully explained in the [TSConfig Reference](../../tsconfig). * Learn how to use a [`tsconfig.json`](tsconfig-json) file. * Learn how to work in an [MSBuild project](compiler-options-in-msbuild). The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/project- config/Compiler%20Options.md) ❤ Contributors to this page: MH OT DR AD JB 64+ Last updated: Mar 11, 2025 # Configuring Watch Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) # Configuring Watch As of TypeScript 3.8 and onward, the Typescript compiler exposes configuration which controls how it watches files and directories. Prior to this version, configuration required the use of environment variables which are still available. ## Background The `--watch` implementation of the compiler relies on Node’s `fs.watch` and `fs.watchFile`. Each of these methods has pros and cons. `fs.watch` relies on file system events to broadcast changes in the watched files and directories. The implementation of this command is OS dependent and unreliable - on many operating systems, it does not work as expected. Additionally, some operating systems limit the number of watches which can exist simultaneously (e.g. some flavors of [Linux](https://man7.org/linux/man- pages/man7/inotify.7.html)). Heavy use of `fs.watch` in large codebases has the potential to exceed these limits and result in undesirable behavior. However, because this implementation relies on an events-based model, CPU use is comparatively light. The compiler typically uses `fs.watch` to watch directories (e.g. source directories included by compiler configuration files and directories in which module resolution failed, among others). TypeScript uses these to augment potential failures in individual file watchers. However, there is a key limitation of this strategy: recursive watching of directories is supported on Windows and macOS, but not on Linux. This suggested a need for additional strategies for file and directory watching. `fs.watchFile` uses polling and thus costs CPU cycles. However, `fs.watchFile` is by far the most reliable mechanism available to subscribe to the events from files and directories of interest. Under this strategy, the TypeScript compiler typically uses `fs.watchFile` to watch source files, config files, and files which appear missing based on reference statements. This means that the degree to which CPU usage will be higher when using `fs.watchFile` depends directly on number of files watched in the codebase. ## Configuring file watching using a `tsconfig.json` The suggested method of configuring watch behavior is through the new `watchOptions` section of `tsconfig.json`. We provide an example configuration below. See the following section for detailed descriptions of the settings available. { // Some typical compiler options "compilerOptions": { "target": "es2020", "moduleResolution": "node" // ... }, // NEW: Options for file/directory watching "watchOptions": { // Use native file system events for files and directories "watchFile": "useFsEvents", "watchDirectory": "useFsEvents", // Poll files for updates more frequently // when they're updated a lot. "fallbackPolling": "dynamicPriority", // Don't coalesce watch notification "synchronousWatchDirectory": true, // Finally, two additional settings for reducing the amount of possible // files to track work from these directories "excludeDirectories": ["**/node_modules", "_build"], "excludeFiles": ["build/fileWhichChangesOften.ts"] } } For further details, see [the release notes for Typescript 3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html#better-directory-watching-on-linux-and- watchoptions). ## Configuring file watching using environment variable `TSC_WATCHFILE` Option | Description ---|--- `PriorityPollingInterval` | Use `fs.watchFile`, but use different polling intervals for source files, config files and missing files `DynamicPriorityPolling` | Use a dynamic queue where frequently modified files are polled at shorter intervals, and unchanged files are polled less frequently `UseFsEvents` | Use `fs.watch`. On operating systems that limit the number of active watches, fall back to `fs.watchFile` when a watcher fails to be created. `UseFsEventsWithFallbackDynamicPolling` | Use `fs.watch`. On operating systems that limit the number of active watches, fall back to dynamic polling queues (as explained in `DynamicPriorityPolling`) `UseFsEventsOnParentDirectory` | Use `fs.watch` on the _parent_ directories of included files (yielding a compromise that results in lower CPU usage than pure `fs.watchFile` but potentially lower accuracy). default (no value specified) | If environment variable `TSC_NONPOLLING_WATCHER` is set to true, use `UseFsEventsOnParentDirectory`. Otherwise, watch files using `fs.watchFile` with `250ms` as the timeout for any file. ## Configuring directory watching using environment variable `TSC_WATCHDIRECTORY` For directory watches on platforms which don’t natively allow recursive directory watching (i.e. non macOS and Windows operating systems) is supported through recursively creating directory watchers for each child directory using different options selected by `TSC_WATCHDIRECTORY`. **NOTE:** On platforms which support native recursive directory watching, the value of `TSC_WATCHDIRECTORY` is ignored. Option | Description ---|--- `RecursiveDirectoryUsingFsWatchFile` | Use `fs.watchFile` to watch included directories and child directories. `RecursiveDirectoryUsingDynamicPriorityPolling` | Use a dynamic polling queue to poll changes to included directories and child directories. default (no value specified) | Use `fs.watch` to watch included directories and child directories. ##### On this page * Background * Configuring file watching using a tsconfig.json * Configuring file watching using environment variable TSC_WATCHFILE * Configuring directory watching using environment variable TSC_WATCHDIRECTORY ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/project- config/Configuring%20Watch.md) ❤ Contributors to this page: SN OT BS JM IO 8+ Last updated: Mar 11, 2025 # Declaration Reference Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](../2/basic-types) * [Everyday Types](../2/everyday-types) * [Narrowing](../2/narrowing) * [More on Functions](../2/functions) * [Object Types](../2/objects) * Type Manipulation * [Creating Types from Types](../2/types-from-types) * [Generics](../2/generics) * [Keyof Type Operator](../2/keyof-types) * [Typeof Type Operator](../2/typeof-types) * [Indexed Access Types](../2/indexed-access-types) * [Conditional Types](../2/conditional-types) * [Mapped Types](../2/mapped-types) * [Template Literal Types](../2/template-literal-types) * [Classes](../2/classes) * [Modules](../2/modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](introduction) * [Declaration Reference](by-example) * [Library Structures](library-structures) * .d.ts Templates * [Modules .d.ts](templates/module-d-ts) * [Module: Plugin](templates/module-plugin-d-ts) * [Module: Class](templates/module-class-d-ts) * [Module: Function](templates/module-function-d-ts) * [Global .d.ts](templates/global-d-ts) * [Global: Modifying Module](templates/global-modifying-module-d-ts) * [Do's and Don'ts](do-s-and-don-ts) * [Deep Dive](deep-dive) * [Publishing](publishing) * [Consumption](consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Declaration Reference The purpose of this guide is to teach you how to write a high-quality definition file. This guide is structured by showing documentation for some API, along with sample usage of that API, and explaining how to write the corresponding declaration. These examples are ordered in approximately increasing order of complexity. ## Objects with Properties _Documentation_ > The global variable `myLib` has a function `makeGreeting` for creating > greetings, and a property `numberOfGreetings` indicating the number of > greetings made so far. _Code_ let result = myLib.makeGreeting("hello, world"); console.log("The computed greeting is:" + result); let count = myLib.numberOfGreetings; _Declaration_ Use `declare namespace` to describe types or values accessed by dotted notation. declare namespace myLib { function makeGreeting(s: string): string; let numberOfGreetings: number; } ## Overloaded Functions _Documentation_ The `getWidget` function accepts a number and returns a Widget, or accepts a string and returns a Widget array. _Code_ let x: Widget = getWidget(43); let arr: Widget[] = getWidget("all of them"); _Declaration_ declare function getWidget(n: number): Widget; declare function getWidget(s: string): Widget[]; ## Reusable Types (Interfaces) _Documentation_ > When specifying a greeting, you must pass a `GreetingSettings` object. This > object has the following properties: > > 1 - greeting: Mandatory string > > 2 - duration: Optional length of time (in milliseconds) > > 3 - color: Optional string, e.g. ‘#ff00ff’ _Code_ greet({ greeting: "hello world", duration: 4000 }); _Declaration_ Use an `interface` to define a type with properties. interface GreetingSettings { greeting: string; duration?: number; color?: string; } declare function greet(setting: GreetingSettings): void; ## Reusable Types (Type Aliases) _Documentation_ > Anywhere a greeting is expected, you can provide a `string`, a function > returning a `string`, or a `Greeter` instance. _Code_ function getGreeting() { return "howdy"; } class MyGreeter extends Greeter {} greet("hello"); greet(getGreeting); greet(new MyGreeter()); _Declaration_ You can use a type alias to make a shorthand for a type: type GreetingLike = string | (() => string) | MyGreeter; declare function greet(g: GreetingLike): void; ## Organizing Types _Documentation_ > The `greeter` object can log to a file or display an alert. You can provide > LogOptions to `.log(...)` and alert options to `.alert(...)` _Code_ const g = new Greeter("Hello"); g.log({ verbose: true }); g.alert({ modal: false, title: "Current Greeting" }); _Declaration_ Use namespaces to organize types. declare namespace GreetingLib { interface LogOptions { verbose?: boolean; } interface AlertOptions { modal: boolean; title?: string; color?: string; } } You can also create nested namespaces in one declaration: declare namespace GreetingLib.Options { // Refer to via GreetingLib.Options.Log interface Log { verbose?: boolean; } interface Alert { modal: boolean; title?: string; color?: string; } } ## Classes _Documentation_ > You can create a greeter by instantiating the `Greeter` object, or create a > customized greeter by extending from it. _Code_ const myGreeter = new Greeter("hello, world"); myGreeter.greeting = "howdy"; myGreeter.showGreeting(); class SpecialGreeter extends Greeter { constructor() { super("Very special greetings"); } } _Declaration_ Use `declare class` to describe a class or class-like object. Classes can have properties and methods as well as a constructor. declare class Greeter { constructor(greeting: string); greeting: string; showGreeting(): void; } ## Global Variables _Documentation_ > The global variable `foo` contains the number of widgets present. _Code_ console.log("Half the number of widgets is " + foo / 2); _Declaration_ Use `declare var` to declare variables. If the variable is read-only, you can use `declare const`. You can also use `declare let` if the variable is block- scoped. /** The number of widgets present */ declare var foo: number; ## Global Functions _Documentation_ > You can call the function `greet` with a string to show a greeting to the > user. _Code_ greet("hello, world"); _Declaration_ Use `declare function` to declare functions. declare function greet(greeting: string): void; ##### On this page * Objects with Properties * Overloaded Functions * Reusable Types (Interfaces) * Reusable Types (Type Aliases) * Organizing Types * Classes * Global Variables * Global Functions ##### Is this page helpful? Yes No [ PreviousIntroduction How to write a high-quality TypeScript Declaration (d.ts) file ](introduction) [ NextLibrary Structures How to structure your d.ts files ](library-structures) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/declaration- files/By%20Example.md) ❤ Contributors to this page: MH OT Y PB RK 7+ Last updated: Mar 11, 2025 # Consumption Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](../2/basic-types) * [Everyday Types](../2/everyday-types) * [Narrowing](../2/narrowing) * [More on Functions](../2/functions) * [Object Types](../2/objects) * Type Manipulation * [Creating Types from Types](../2/types-from-types) * [Generics](../2/generics) * [Keyof Type Operator](../2/keyof-types) * [Typeof Type Operator](../2/typeof-types) * [Indexed Access Types](../2/indexed-access-types) * [Conditional Types](../2/conditional-types) * [Mapped Types](../2/mapped-types) * [Template Literal Types](../2/template-literal-types) * [Classes](../2/classes) * [Modules](../2/modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](introduction) * [Declaration Reference](by-example) * [Library Structures](library-structures) * .d.ts Templates * [Modules .d.ts](templates/module-d-ts) * [Module: Plugin](templates/module-plugin-d-ts) * [Module: Class](templates/module-class-d-ts) * [Module: Function](templates/module-function-d-ts) * [Global .d.ts](templates/global-d-ts) * [Global: Modifying Module](templates/global-modifying-module-d-ts) * [Do's and Don'ts](do-s-and-don-ts) * [Deep Dive](deep-dive) * [Publishing](publishing) * [Consumption](consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Consumption ## Downloading Getting type declarations requires no tools apart from npm. As an example, getting the declarations for a library like lodash takes nothing more than the following command npm install --save-dev @types/lodash It is worth noting that if the npm package already includes its declaration file as described in [Publishing](publishing), downloading the corresponding `@types` package is not needed. ## Consuming From there you’ll be able to use lodash in your TypeScript code with no fuss. This works for both modules and global code. For example, once you’ve `npm install`-ed your type declarations, you can use imports and write import * as _ from "lodash"; _.padStart("Hello TypeScript!", 20, " "); or if you’re not using modules, you can just use the global variable `_`. _.padStart("Hello TypeScript!", 20, " "); ## Searching For the most part, type declaration packages should always have the same name as the package name on `npm`, but prefixed with `@types/`, but if you need, you can use the [Yarn package search](https://yarnpkg.com/) to find the package for your favorite library. > Note: if the declaration file you are searching for is not present, you can > always contribute one back and help out the next developer looking for it. > Please see the DefinitelyTyped [contribution guidelines > page](https://definitelytyped.org/guides/contributing.html) for details. ##### On this page * Downloading * Consuming * Searching ##### Is this page helpful? Yes No [ PreviousPublishing How to get your d.ts files to users ](publishing) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/declaration- files/Consumption.md) ❤ Contributors to this page: MH OT IO KO EB 5+ Last updated: Mar 11, 2025 # Deep Dive Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](../2/basic-types) * [Everyday Types](../2/everyday-types) * [Narrowing](../2/narrowing) * [More on Functions](../2/functions) * [Object Types](../2/objects) * Type Manipulation * [Creating Types from Types](../2/types-from-types) * [Generics](../2/generics) * [Keyof Type Operator](../2/keyof-types) * [Typeof Type Operator](../2/typeof-types) * [Indexed Access Types](../2/indexed-access-types) * [Conditional Types](../2/conditional-types) * [Mapped Types](../2/mapped-types) * [Template Literal Types](../2/template-literal-types) * [Classes](../2/classes) * [Modules](../2/modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](introduction) * [Declaration Reference](by-example) * [Library Structures](library-structures) * .d.ts Templates * [Modules .d.ts](templates/module-d-ts) * [Module: Plugin](templates/module-plugin-d-ts) * [Module: Class](templates/module-class-d-ts) * [Module: Function](templates/module-function-d-ts) * [Global .d.ts](templates/global-d-ts) * [Global: Modifying Module](templates/global-modifying-module-d-ts) * [Do's and Don'ts](do-s-and-don-ts) * [Deep Dive](deep-dive) * [Publishing](publishing) * [Consumption](consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Deep Dive ## Declaration File Theory: A Deep Dive Structuring modules to give the exact API shape you want can be tricky. For example, we might want a module that can be invoked with or without `new` to produce different types, has a variety of named types exposed in a hierarchy, and has some properties on the module object as well. By reading this guide, you’ll have the tools to write complex declaration files that expose a friendly API surface. This guide focuses on module (or UMD) libraries because the options here are more varied. ## Key Concepts You can fully understand how to make any shape of declaration by understanding some key concepts of how TypeScript works. ### Types If you’re reading this guide, you probably already roughly know what a type in TypeScript is. To be more explicit, though, a _type_ is introduced with: * A type alias declaration (`type sn = number | string;`) * An interface declaration (`interface I { x: number[]; }`) * A class declaration (`class C { }`) * An enum declaration (`enum E { A, B, C }`) * An `import` declaration which refers to a type Each of these declaration forms creates a new type name. ### Values As with types, you probably already understand what a value is. Values are runtime names that we can reference in expressions. For example `let x = 5;` creates a value called `x`. Again, being explicit, the following things create values: * `let`, `const`, and `var` declarations * A `namespace` or `module` declaration which contains a value * An `enum` declaration * A `class` declaration * An `import` declaration which refers to a value * A `function` declaration ### Namespaces Types can exist in _namespaces_. For example, if we have the declaration `let x: A.B.C`, we say that the type `C` comes from the `A.B` namespace. This distinction is subtle and important — here, `A.B` is not necessarily a type or a value. ## Simple Combinations: One name, multiple meanings Given a name `A`, we might find up to three different meanings for `A`: a type, a value or a namespace. How the name is interpreted depends on the context in which it is used. For example, in the declaration `let m: A.A = A;`, `A` is used first as a namespace, then as a type name, then as a value. These meanings might end up referring to entirely different declarations! This may seem confusing, but it’s actually very convenient as long as we don’t excessively overload things. Let’s look at some useful aspects of this combining behavior. ### Built-in Combinations Astute readers will notice that, for example, `class` appeared in both the _type_ and _value_ lists. The declaration `class C { }` creates two things: a _type_ `C` which refers to the instance shape of the class, and a _value_ `C` which refers to the constructor function of the class. Enum declarations behave similarly. ### User Combinations Let’s say we wrote a module file `foo.d.ts`: export var SomeVar: { a: SomeType }; export interface SomeType { count: number; } Then consumed it: import * as foo from "./foo"; let x: foo.SomeType = foo.SomeVar.a; console.log(x.count); This works well enough, but we might imagine that `SomeType` and `SomeVar` were very closely related such that you’d like them to have the same name. We can use combining to present these two different objects (the value and the type) under the same name `Bar`: export var Bar: { a: Bar }; export interface Bar { count: number; } This presents a very good opportunity for destructuring in the consuming code: import { Bar } from "./foo"; let x: Bar = Bar.a; console.log(x.count); Again, we’ve used `Bar` as both a type and a value here. Note that we didn’t have to declare the `Bar` value as being of the `Bar` type — they’re independent. ## Advanced Combinations Some kinds of declarations can be combined across multiple declarations. For example, `class C { }` and `interface C { }` can co-exist and both contribute properties to the `C` types. This is legal as long as it does not create a conflict. A general rule of thumb is that values always conflict with other values of the same name unless they are declared as `namespace`s, types will conflict if they are declared with a type alias declaration (`type s = string`), and namespaces never conflict. Let’s see how this can be used. ### Adding using an `interface` We can add additional members to an `interface` with another `interface` declaration: interface Foo { x: number; } // ... elsewhere ... interface Foo { y: number; } let a: Foo = ...; console.log(a.x + a.y); // OK This also works with classes: class Foo { x: number; } // ... elsewhere ... interface Foo { y: number; } let a: Foo = ...; console.log(a.x + a.y); // OK Note that we cannot add to type aliases (`type s = string;`) using an interface. ### Adding using a `namespace` A `namespace` declaration can be used to add new types, values, and namespaces in any way which does not create a conflict. For example, we can add a static member to a class: class C {} // ... elsewhere ... namespace C { export let x: number; } let y = C.x; // OK Note that in this example, we added a value to the _static_ side of `C` (its constructor function). This is because we added a _value_ , and the container for all values is another value (types are contained by namespaces, and namespaces are contained by other namespaces). We could also add a namespaced type to a class: class C {} // ... elsewhere ... namespace C { export interface D {} } let y: C.D; // OK In this example, there wasn’t a namespace `C` until we wrote the `namespace` declaration for it. The meaning `C` as a namespace doesn’t conflict with the value or type meanings of `C` created by the class. Finally, we could perform many different merges using `namespace` declarations. This isn’t a particularly realistic example, but shows all sorts of interesting behavior: namespace X { export interface Y {} export class Z {} } // ... elsewhere ... namespace X { export var Y: number; export namespace Z { export class C {} } } type X = string; In this example, the first block creates the following name meanings: * A value `X` (because the `namespace` declaration contains a value, `Z`) * A namespace `X` (because the `namespace` declaration contains a type, `Y`) * A type `Y` in the `X` namespace * A type `Z` in the `X` namespace (the instance shape of the class) * A value `Z` that is a property of the `X` value (the constructor function of the class) The second block creates the following name meanings: * A value `Y` (of type `number`) that is a property of the `X` value * A namespace `Z` * A value `Z` that is a property of the `X` value * A type `C` in the `X.Z` namespace * A value `C` that is a property of the `X.Z` value * A type `X` ##### On this page * Declaration File Theory: A Deep Dive * Key Concepts * Types * Values * Namespaces * Simple Combinations: One name, multiple meanings * Built-in Combinations * User Combinations * Advanced Combinations * Adding using an interface * Adding using a namespace ##### Is this page helpful? Yes No [ PreviousDo's and Don'ts Recommendations for writing d.ts files ](do-s-and- don-ts) [ NextPublishing How to get your d.ts files to users ](publishing) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/declaration- files/Deep%20Dive.md) ❤ Contributors to this page: MH OT 1+ Last updated: Mar 11, 2025 # Do's and Don'ts Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](../2/basic-types) * [Everyday Types](../2/everyday-types) * [Narrowing](../2/narrowing) * [More on Functions](../2/functions) * [Object Types](../2/objects) * Type Manipulation * [Creating Types from Types](../2/types-from-types) * [Generics](../2/generics) * [Keyof Type Operator](../2/keyof-types) * [Typeof Type Operator](../2/typeof-types) * [Indexed Access Types](../2/indexed-access-types) * [Conditional Types](../2/conditional-types) * [Mapped Types](../2/mapped-types) * [Template Literal Types](../2/template-literal-types) * [Classes](../2/classes) * [Modules](../2/modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](introduction) * [Declaration Reference](by-example) * [Library Structures](library-structures) * .d.ts Templates * [Modules .d.ts](templates/module-d-ts) * [Module: Plugin](templates/module-plugin-d-ts) * [Module: Class](templates/module-class-d-ts) * [Module: Function](templates/module-function-d-ts) * [Global .d.ts](templates/global-d-ts) * [Global: Modifying Module](templates/global-modifying-module-d-ts) * [Do's and Don'ts](do-s-and-don-ts) * [Deep Dive](deep-dive) * [Publishing](publishing) * [Consumption](consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Do's and Don'ts ## General Types ### `Number`, `String`, `Boolean`, `Symbol` and `Object` ❌ **Don’t** ever use the types `Number`, `String`, `Boolean`, `Symbol`, or `Object` These types refer to non-primitive boxed objects that are almost never used appropriately in JavaScript code. /* WRONG */ function reverse(s: String): String; ✅ **Do** use the types `number`, `string`, `boolean`, and `symbol`. /* OK */ function reverse(s: string): string; Instead of `Object`, use the non-primitive `object` type ([added in TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-2.html#object-type)). ### Generics ❌ **Don’t** ever have a generic type which doesn’t use its type parameter. See more details in [TypeScript FAQ page](https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-type- inference-work-on-this-interface-interface-foot--). ### any ❌ **Don’t** use `any` as a type unless you are in the process of migrating a JavaScript project to TypeScript. The compiler _effectively_ treats `any` as “please turn off type checking for this thing”. It is similar to putting an `@ts-ignore` comment around every usage of the variable. This can be very helpful when you are first migrating a JavaScript project to TypeScript as you can set the type for stuff you haven’t migrated yet as `any`, but in a full TypeScript project you are disabling type checking for any parts of your program that use it. In cases where you don’t know what type you want to accept, or when you want to accept anything because you will be blindly passing it through without interacting with it, you can use [`unknown`](https://www.typescriptlang.org/play/#example/unknown-and-never). ## Callback Types ### Return Types of Callbacks ❌ **Don’t** use the return type `any` for callbacks whose value will be ignored: /* WRONG */ function fn(x: () => any) { x(); } ✅ **Do** use the return type `void` for callbacks whose value will be ignored: /* OK */ function fn(x: () => void) { x(); } ❔ **Why:** Using `void` is safer because it prevents you from accidentally using the return value of `x` in an unchecked way: function fn(x: () => void) { var k = x(); // oops! meant to do something else k.doSomething(); // error, but would be OK if the return type had been 'any' } ### Optional Parameters in Callbacks ❌ **Don’t** use optional parameters in callbacks unless you really mean it: /* WRONG */ interface Fetcher { getObject(done: (data: unknown, elapsedTime?: number) => void): void; } This has a very specific meaning: the `done` callback might be invoked with 1 argument or might be invoked with 2 arguments. The author probably intended to say that the callback might not care about the `elapsedTime` parameter, but there’s no need to make the parameter optional to accomplish this — it’s always legal to provide a callback that accepts fewer arguments. ✅ **Do** write callback parameters as non-optional: /* OK */ interface Fetcher { getObject(done: (data: unknown, elapsedTime: number) => void): void; } ### Overloads and Callbacks ❌ **Don’t** write separate overloads that differ only on callback arity: /* WRONG */ declare function beforeAll(action: () => void, timeout?: number): void; declare function beforeAll( action: (done: DoneFn) => void, timeout?: number ): void; ✅ **Do** write a single overload using the maximum arity: /* OK */ declare function beforeAll( action: (done: DoneFn) => void, timeout?: number ): void; ❔ **Why:** It’s always legal for a callback to disregard a parameter, so there’s no need for the shorter overload. Providing a shorter callback first allows incorrectly-typed functions to be passed in because they match the first overload. ## Function Overloads ### Ordering ❌ **Don’t** put more general overloads before more specific overloads: /* WRONG */ declare function fn(x: unknown): unknown; declare function fn(x: HTMLElement): number; declare function fn(x: HTMLDivElement): string; var myElem: HTMLDivElement; var x = fn(myElem); // x: unknown, wat? ✅ **Do** sort overloads by putting the more general signatures after more specific signatures: /* OK */ declare function fn(x: HTMLDivElement): string; declare function fn(x: HTMLElement): number; declare function fn(x: unknown): unknown; var myElem: HTMLDivElement; var x = fn(myElem); // x: string, :) ❔ **Why:** TypeScript chooses the _first matching overload_ when resolving function calls. When an earlier overload is “more general” than a later one, the later one is effectively hidden and cannot be called. ### Use Optional Parameters ❌ **Don’t** write several overloads that differ only in trailing parameters: /* WRONG */ interface Example { diff(one: string): number; diff(one: string, two: string): number; diff(one: string, two: string, three: boolean): number; } ✅ **Do** use optional parameters whenever possible: /* OK */ interface Example { diff(one: string, two?: string, three?: boolean): number; } Note that this collapsing should only occur when all overloads have the same return type. ❔ **Why:** This is important for two reasons. TypeScript resolves signature compatibility by seeing if any signature of the target can be invoked with the arguments of the source, _and extraneous arguments are allowed_. This code, for example, exposes a bug only when the signature is correctly written using optional parameters: function fn(x: (a: string, b: number, c: number) => void) {} var x: Example; // When written with overloads, OK -- used first overload // When written with optionals, correctly an error fn(x.diff); The second reason is when a consumer uses the “strict null checking” feature of TypeScript. Because unspecified parameters appear as `undefined` in JavaScript, it’s usually fine to pass an explicit `undefined` to a function with optional arguments. This code, for example, should be OK under strict nulls: var x: Example; // When written with overloads, incorrectly an error because of passing 'undefined' to 'string' // When written with optionals, correctly OK x.diff("something", true ? undefined : "hour"); ### Use Union Types ❌ **Don’t** write overloads that differ by type in only one argument position: /* WRONG */ interface Moment { utcOffset(): number; utcOffset(b: number): Moment; utcOffset(b: string): Moment; } ✅ **Do** use union types whenever possible: /* OK */ interface Moment { utcOffset(): number; utcOffset(b: number | string): Moment; } Note that we didn’t make `b` optional here because the return types of the signatures differ. ❔ **Why:** This is important for people who are “passing through” a value to your function: function fn(x: string): Moment; function fn(x: number): Moment; function fn(x: number | string) { // When written with separate overloads, incorrectly an error // When written with union types, correctly OK return moment().utcOffset(x); } ##### On this page * General Types * Number, String, Boolean, Symbol and Object * Generics * any * Callback Types * Return Types of Callbacks * Optional Parameters in Callbacks * Overloads and Callbacks * Function Overloads * Ordering * Use Optional Parameters * Use Union Types ##### Is this page helpful? Yes No [ NextDeep Dive How do d.ts files work, a deep dive ](deep-dive) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/declaration- files/Do's%20and%20Don'ts.md) ❤ Contributors to this page: MH OT MZ MF J 15+ Last updated: Mar 11, 2025 # Creating .d.ts Files from .js files Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](../2/basic-types) * [Everyday Types](../2/everyday-types) * [Narrowing](../2/narrowing) * [More on Functions](../2/functions) * [Object Types](../2/objects) * Type Manipulation * [Creating Types from Types](../2/types-from-types) * [Generics](../2/generics) * [Keyof Type Operator](../2/keyof-types) * [Typeof Type Operator](../2/typeof-types) * [Indexed Access Types](../2/indexed-access-types) * [Conditional Types](../2/conditional-types) * [Mapped Types](../2/mapped-types) * [Template Literal Types](../2/template-literal-types) * [Classes](../2/classes) * [Modules](../2/modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](introduction) * [Declaration Reference](by-example) * [Library Structures](library-structures) * .d.ts Templates * [Modules .d.ts](templates/module-d-ts) * [Module: Plugin](templates/module-plugin-d-ts) * [Module: Class](templates/module-class-d-ts) * [Module: Function](templates/module-function-d-ts) * [Global .d.ts](templates/global-d-ts) * [Global: Modifying Module](templates/global-modifying-module-d-ts) * [Do's and Don'ts](do-s-and-don-ts) * [Deep Dive](deep-dive) * [Publishing](publishing) * [Consumption](consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Creating .d.ts Files from .js files [With TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html#--declaration-and---allowjs), TypeScript added support for generating .d.ts files from JavaScript using JSDoc syntax. This set up means you can own the editor experience of TypeScript-powered editors without porting your project to TypeScript, or having to maintain .d.ts files in your codebase. TypeScript supports most JSDoc tags, you can find [the reference here](../type-checking-javascript-files#supported-jsdoc). ## Setting up your Project to emit .d.ts files To add creation of .d.ts files in your project, you will need to do up-to four steps: * Add TypeScript to your dev dependencies * Add a `tsconfig.json` to configure TypeScript * Run the TypeScript compiler to generate the corresponding d.ts files for JS files * (optional) Edit your package.json to reference the types ### Adding TypeScript You can learn how to do this in our [installation page](https://www.typescriptlang.org/download). ### TSConfig The TSConfig is a jsonc file which configures both your compiler flags, and declare where to find files. In this case, you will want a file like the following: { // Change this to match your project "include": ["src/**/*"], "compilerOptions": { // Tells TypeScript to read JS files, as // normally they are ignored as source files "allowJs": true, // Generate d.ts files "declaration": true, // This compiler run should // only output d.ts files "emitDeclarationOnly": true, // Types should go into this directory. // Removing this would place the .d.ts files // next to the .js files "outDir": "dist", // go to js file when using IDE functions like // "Go to Definition" in VSCode "declarationMap": true } } You can learn more about the options in the [tsconfig reference](../../../tsconfig). An alternative to using a TSConfig file is the CLI, this is the same behavior as a CLI command. npx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types ## Run the compiler You can learn how to do this in our [installation page](https://www.typescriptlang.org/download). You want to make sure these files are included in your package if you have the files in your project’s `.gitignore`. ## Editing the package.json TypeScript replicates the node resolution for modules in a `package.json`, with an additional step for finding .d.ts files. Roughly, the resolution will first check the optional `types` field, then the `"main"` field, and finally will try `index.d.ts` in the root. Package.json | Location of default .d.ts ---|--- No “types” field | checks “main”, then index.d.ts “types”: “main.d.ts” | main.d.ts “types”: “./dist/main.js” | ./dist/main.d.ts If absent, then “main” is used Package.json | Location of default .d.ts ---|--- No “main” field | index.d.ts “main”:“index.js” | index.d.ts “main”:“./dist/index.js” | ./dist/index.d.ts ## Tips If you’d like to write tests for your .d.ts files, try [tsd](https://github.com/SamVerschueren/tsd) or [TSTyche](https://github.com/tstyche/tstyche). ##### On this page * Setting up your Project to emit .d.ts files * Adding TypeScript * TSConfig * Run the compiler * Editing the package.json * Tips ##### Is this page helpful? Yes No [ PreviousJSDoc Reference What JSDoc does TypeScript-powered JavaScript support? ](../jsdoc-supported-types) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/javascript/Creating%20DTS%20files%20From%20JS.md) ❤ Contributors to this page: OT TM SG JB SW 3+ Last updated: Mar 11, 2025 # Introduction Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](../2/basic-types) * [Everyday Types](../2/everyday-types) * [Narrowing](../2/narrowing) * [More on Functions](../2/functions) * [Object Types](../2/objects) * Type Manipulation * [Creating Types from Types](../2/types-from-types) * [Generics](../2/generics) * [Keyof Type Operator](../2/keyof-types) * [Typeof Type Operator](../2/typeof-types) * [Indexed Access Types](../2/indexed-access-types) * [Conditional Types](../2/conditional-types) * [Mapped Types](../2/mapped-types) * [Template Literal Types](../2/template-literal-types) * [Classes](../2/classes) * [Modules](../2/modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](introduction) * [Declaration Reference](by-example) * [Library Structures](library-structures) * .d.ts Templates * [Modules .d.ts](templates/module-d-ts) * [Module: Plugin](templates/module-plugin-d-ts) * [Module: Class](templates/module-class-d-ts) * [Module: Function](templates/module-function-d-ts) * [Global .d.ts](templates/global-d-ts) * [Global: Modifying Module](templates/global-modifying-module-d-ts) * [Do's and Don'ts](do-s-and-don-ts) * [Deep Dive](deep-dive) * [Publishing](publishing) * [Consumption](consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Introduction The Declaration Files section is designed to teach you how to write a high- quality TypeScript Declaration File. We need to assume basic familiarity with the TypeScript language in order to get started. If you haven’t already, you should read the [TypeScript Handbook](../2/basic- types) to familiarize yourself with basic concepts, especially types and modules. The most common case for learning how .d.ts files work is that you’re typing an npm package with no types. In that case, you can jump straight to [Modules .d.ts](templates/module-d-ts). The Declaration Files section is broken down into the following sections. We are often faced with writing a declaration file when we only have examples of the underlying library to guide us. The [Declaration Reference](by-example) section shows many common API patterns and how to write declarations for each of them. This guide is aimed at the TypeScript novice who may not yet be familiar with every language construct in TypeScript. The [Library Structures](library-structures) guide helps you understand common library formats and how to write a proper declaration file for each format. If you’re editing an existing file, you probably don’t need to read this section. Authors of new declaration files are strongly encouraged to read this section to properly understand how the format of the library influences the writing of the declaration file. In the Template section you’ll find a number of declaration files that serve as a useful starting point when writing a new file. If you already know what your structure is, see the d.ts Template section in the sidebar. Many common mistakes in declaration files can be easily avoided. The [Do’s and Don’ts](do-s-and-don-ts) section identifies common errors, describes how to detect them, and how to fix them. Everyone should read this section to help themselves avoid common mistakes. For seasoned authors interested in the underlying mechanics of how declaration files work, the [Deep Dive](deep-dive) section explains many advanced concepts in declaration writing, and shows how to leverage these concepts to create cleaner and more intuitive declaration files. The [Publishing](publishing) section explains how to publish your declaration files to an npm package, and shows how to manage your dependent packages. For JavaScript library users, the [Consumption](consumption) section offers a few simple steps to locate and install corresponding declaration files. ##### On this page * Declaration Reference * Library Structures * Do’s and Don’ts * Deep Dive * Publish to npm * Find and Install Declaration Files ##### Is this page helpful? Yes No [ NextDeclaration Reference How to create a d.ts file for a module ](by- example) The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/declaration- files/Introduction.md) ❤ Contributors to this page: MH OT JW NR DK 11+ Last updated: Mar 11, 2025 # Library Structures Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](../2/basic-types) * [Everyday Types](../2/everyday-types) * [Narrowing](../2/narrowing) * [More on Functions](../2/functions) * [Object Types](../2/objects) * Type Manipulation * [Creating Types from Types](../2/types-from-types) * [Generics](../2/generics) * [Keyof Type Operator](../2/keyof-types) * [Typeof Type Operator](../2/typeof-types) * [Indexed Access Types](../2/indexed-access-types) * [Conditional Types](../2/conditional-types) * [Mapped Types](../2/mapped-types) * [Template Literal Types](../2/template-literal-types) * [Classes](../2/classes) * [Modules](../2/modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](../modules/introduction) * [Theory](../modules/theory) * Guides * [Choosing Compiler Options](../modules/guides/choosing-compiler-options) * [Reference](../modules/reference) * Appendices * [ESM/CJS Interoperability](../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](introduction) * [Declaration Reference](by-example) * [Library Structures](library-structures) * .d.ts Templates * [Modules .d.ts](templates/module-d-ts) * [Module: Plugin](templates/module-plugin-d-ts) * [Module: Class](templates/module-class-d-ts) * [Module: Function](templates/module-function-d-ts) * [Global .d.ts](templates/global-d-ts) * [Global: Modifying Module](templates/global-modifying-module-d-ts) * [Do's and Don'ts](do-s-and-don-ts) * [Deep Dive](deep-dive) * [Publishing](publishing) * [Consumption](consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Library Structures Broadly speaking, the way you _structure_ your declaration file depends on how the library is consumed. There are many ways of offering a library for consumption in JavaScript, and you’ll need to write your declaration file to match it. This guide covers how to identify common library patterns, and how to write declaration files which correspond to that pattern. Each type of major library structuring pattern has a corresponding file in the [Templates](templates) section. You can start with these templates to help you get going faster. ## Identifying Kinds of Libraries First, we’ll review the kinds of libraries TypeScript declaration files can represent. We’ll briefly show how each kind of library is _used_ , how it is _written_ , and list some example libraries from the real world. Identifying the structure of a library is the first step in writing its declaration file. We’ll give hints on how to identify structure both based on its _usage_ and its _code_. Depending on the library’s documentation and organization, one might be easier than the other. We recommend using whichever is more comfortable to you. ### What should you look for? Question to ask yourself while looking at a library you are trying to type. 1. How do you obtain the library? For example, can you _only_ get it through npm or only from a CDN? 2. How would you import it? Does it add a global object? Does it use `require` or `import`/`export` statements? ### Smaller samples for different types of libraries ### Modular Libraries Almost every modern Node.js library falls into the module family. These type of libraries only work in a JS environment with a module loader. For example, `express` only works in Node.js and must be loaded using the CommonJS `require` function. ECMAScript 2015 (also known as ES2015, ECMAScript 6, and ES6), CommonJS, and RequireJS have similar notions of _importing_ a _module_. In JavaScript CommonJS (Node.js), for example, you would write var fs = require("fs"); In TypeScript or ES6, the `import` keyword serves the same purpose: import * as fs from "fs"; You’ll typically see modular libraries include one of these lines in their documentation: var someLib = require("someLib"); or define(..., ['someLib'], function(someLib) { }); As with global modules, you might see these examples in the documentation of a UMD module, so be sure to check the code or documentation. #### Identifying a Module Library from Code Modular libraries will typically have at least some of the following: * Unconditional calls to `require` or `define` * Declarations like `import * as a from 'b';` or `export c;` * Assignments to `exports` or `module.exports` They will rarely have: * Assignments to properties of `window` or `global` #### Templates For Modules There are four templates available for modules, [`module.d.ts`](templates/module-d-ts), [`module- class.d.ts`](templates/module-class-d-ts), [`module- function.d.ts`](templates/module-function-d-ts) and [`module- plugin.d.ts`](templates/module-plugin-d-ts). You should first read [`module.d.ts`](templates/module-d-ts) for an overview on the way they all work. Then use the template [`module-function.d.ts`](templates/module-function-d-ts) if your module can be _called_ like a function: const x = require("foo"); // Note: calling 'x' as a function const y = x(42); Use the template [`module-class.d.ts`](templates/module-class-d-ts) if your module can be _constructed_ using `new`: const x = require("bar"); // Note: using 'new' operator on the imported variable const y = new x("hello"); If you have a module which when imported, makes changes to other modules use template [`module-plugin.d.ts`](templates/module-plugin-d-ts): const jest = require("jest"); require("jest-matchers-files"); ### Global Libraries A _global_ library is one that can be accessed from the global scope (i.e. without using any form of `import`). Many libraries simply expose one or more global variables for use. For example, if you were using [jQuery](https://jquery.com/), the `$` variable can be used by simply referring to it: $(() => { console.log("hello!"); }); You’ll usually see guidance in the documentation of a global library of how to use the library in an HTML script tag: Today, most popular globally-accessible libraries are actually written as UMD libraries (see below). UMD library documentation is hard to distinguish from global library documentation. Before writing a global declaration file, make sure the library isn’t actually UMD. #### Identifying a Global Library from Code Global library code is usually extremely simple. A global “Hello, world” library might look like this: function createGreeting(s) { return "Hello, " + s; } or like this: // Web window.createGreeting = function (s) { return "Hello, " + s; }; // Node global.createGreeting = function (s) { return "Hello, " + s; }; // Potentially any runtime globalThis.createGreeting = function (s) { return "Hello, " + s; }; When looking at the code of a global library, you’ll usually see: * Top-level `var` statements or `function` declarations * One or more assignments to `window.someName` * Assumptions that DOM primitives like `document` or `window` exist You _won’t_ see: * Checks for, or usage of, module loaders like `require` or `define` * CommonJS/Node.js-style imports of the form `var fs = require("fs");` * Calls to `define(...)` * Documentation describing how to `require` or import the library #### Examples of Global Libraries Because it’s usually easy to turn a global library into a UMD library, very few popular libraries are still written in the global style. However, libraries that are small and require the DOM (or have _no_ dependencies) may still be global. #### Global Library Template The template file [`global.d.ts`](templates/global-d-ts) defines an example library `myLib`. Be sure to read the “Preventing Name Conflicts” footnote. ### _UMD_ A _UMD_ module is one that can _either_ be used as module (through an import), or as a global (when run in an environment without a module loader). Many popular libraries, such as [Moment.js](https://momentjs.com/), are written this way. For example, in Node.js or using RequireJS, you would write: import moment = require("moment"); console.log(moment.format()); whereas in a vanilla browser environment you would write: console.log(moment.format()); #### Identifying a UMD library [UMD modules](https://github.com/umdjs/umd) check for the existence of a module loader environment. This is an easy-to-spot pattern that looks something like this: (function (root, factory) { if (typeof define === "function" && define.amd) { define(["libName"], factory); } else if (typeof module === "object" && module.exports) { module.exports = factory(require("libName")); } else { root.returnExports = factory(root.libName); } }(this, function (b) { If you see tests for `typeof define`, `typeof window`, or `typeof module` in the code of a library, especially at the top of the file, it’s almost always a UMD library. Documentation for UMD libraries will also often demonstrate a “Using in Node.js” example showing `require`, and a “Using in the browser” example showing using a ` Today, most popular globally-accessible libraries are actually written as UMD libraries (see below). UMD library documentation is hard to distinguish from global library documentation. Before writing a global declaration file, make sure the library isn’t actually UMD. ## Identifying a Global Library from Code Global library code is usually extremely simple. A global “Hello, world” library might look like this: function createGreeting(s) { return "Hello, " + s; } or like this: window.createGreeting = function (s) { return "Hello, " + s; }; When looking at the code of a global library, you’ll usually see: * Top-level `var` statements or `function` declarations * One or more assignments to `window.someName` * Assumptions that DOM primitives like `document` or `window` exist You _won’t_ see: * Checks for, or usage of, module loaders like `require` or `define` * CommonJS/Node.js-style imports of the form `var fs = require("fs");` * Calls to `define(...)` * Documentation describing how to `require` or import the library ## Examples of Global Libraries Because it’s usually easy to turn a global library into a UMD library, very few popular libraries are still written in the global style. However, libraries that are small and require the DOM (or have _no_ dependencies) may still be global. ## Global Library Template You can see an example DTS below: // Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] // Project: [~THE PROJECT NAME~] // Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]> /*~ If this library is callable (e.g. can be invoked as myLib(3)), *~ include those call signatures here. *~ Otherwise, delete this section. */ declare function myLib(a: string): string; declare function myLib(a: number): number; /*~ If you want the name of this library to be a valid type name, *~ you can do so here. *~ *~ For example, this allows us to write 'var x: myLib'; *~ Be sure this actually makes sense! If it doesn't, just *~ delete this declaration and add types inside the namespace below. */ interface myLib { name: string; length: number; extras?: string[]; } /*~ If your library has properties exposed on a global variable, *~ place them here. *~ You should also place types (interfaces and type alias) here. */ declare namespace myLib { //~ We can write 'myLib.timeout = 50;' let timeout: number; //~ We can access 'myLib.version', but not change it const version: string; //~ There's some class we can create via 'let c = new myLib.Cat(42)' //~ Or reference e.g. 'function f(c: myLib.Cat) { ... } class Cat { constructor(n: number); //~ We can read 'c.age' from a 'Cat' instance readonly age: number; //~ We can invoke 'c.purr()' from a 'Cat' instance purr(): void; } //~ We can declare a variable as //~ 'var s: myLib.CatSettings = { weight: 5, name: "Maru" };' interface CatSettings { weight: number; name: string; tailLength?: number; } //~ We can write 'const v: myLib.VetID = 42;' //~ or 'const v: myLib.VetID = "bob";' type VetID = string | number; //~ We can invoke 'myLib.checkCat(c)' or 'myLib.checkCat(c, v);' function checkCat(c: Cat, s?: VetID); } ##### On this page * Global Libraries * Identifying a Global Library from Code * Examples of Global Libraries * Global Library Template ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/declaration- files/templates/global.d.ts.md) ❤ Contributors to this page: MH OT 1+ Last updated: Mar 11, 2025 # Global: Modifying Module Was this page helpful? * Get Started * [TS for the New Programmer](../../typescript-from-scratch) * [TypeScript for JS Programmers](../../typescript-in-5-minutes) * [TS for Java/C# Programmers](../../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../../intro) * [The Basics](../../2/basic-types) * [Everyday Types](../../2/everyday-types) * [Narrowing](../../2/narrowing) * [More on Functions](../../2/functions) * [Object Types](../../2/objects) * Type Manipulation * [Creating Types from Types](../../2/types-from-types) * [Generics](../../2/generics) * [Keyof Type Operator](../../2/keyof-types) * [Typeof Type Operator](../../2/typeof-types) * [Indexed Access Types](../../2/indexed-access-types) * [Conditional Types](../../2/conditional-types) * [Mapped Types](../../2/mapped-types) * [Template Literal Types](../../2/template-literal-types) * [Classes](../../2/classes) * [Modules](../../2/modules) * Reference * [Utility Types](../../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../../decorators) * [Declaration Merging](../../declaration-merging) * [Enums](../../enums) * [Iterators and Generators](../../iterators-and-generators) * [JSX](../../jsx) * [Mixins](../../mixins) * [Namespaces](../../namespaces) * [Namespaces and Modules](../../namespaces-and-modules) * [Symbols](../../symbols) * [Triple-Slash Directives](../../triple-slash-directives) * [Type Compatibility](../../type-compatibility) * [Type Inference](../../type-inference) * [Variable Declaration](../../variable-declarations) * Modules Reference * [Introduction](../../modules/introduction) * [Theory](../../modules/theory) * Guides * [Choosing Compiler Options](../../modules/guides/choosing-compiler-options) * [Reference](../../modules/reference) * Appendices * [ESM/CJS Interoperability](../../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../../asp-net-core) * [Gulp](../../gulp) * [DOM Manipulation](../../dom-manipulation) * [Migrating from JavaScript](../../migrating-from-javascript) * [Using Babel with TypeScript](../../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../introduction) * [Declaration Reference](../by-example) * [Library Structures](../library-structures) * .d.ts Templates * [Modules .d.ts](module-d-ts) * [Module: Plugin](module-plugin-d-ts) * [Module: Class](module-class-d-ts) * [Module: Function](module-function-d-ts) * [Global .d.ts](global-d-ts) * [Global: Modifying Module](global-modifying-module-d-ts) * [Do's and Don'ts](../do-s-and-don-ts) * [Deep Dive](../deep-dive) * [Publishing](../publishing) * [Consumption](../consumption) * JavaScript * [JS Projects Utilizing TypeScript](../../intro-to-js-ts) * [Type Checking JavaScript Files](../../type-checking-javascript-files) * [JSDoc Reference](../../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../dts-from-js) * Project Configuration * [What is a tsconfig.json](../../tsconfig-json) * [Compiler Options in MSBuild](../../compiler-options-in-msbuild) * [TSConfig Reference](../../../../tsconfig/index) * [tsc CLI Options](../../compiler-options) * [Project References](../../project-references) * [Integrating with Build Tools](../../integrating-with-build-tools) * [Configuring Watch](../../configuring-watch) * [Nightly Builds](../../nightly-builds) # Global: Modifying Module ## _Global-modifying Modules_ A _global-modifying module_ alters existing values in the global scope when they are imported. For example, there might exist a library which adds new members to `String.prototype` when imported. This pattern is somewhat dangerous due to the possibility of runtime conflicts, but we can still write a declaration file for it. ## Identifying global-modifying modules Global-modifying modules are generally easy to identify from their documentation. In general, they’re similar to global plugins, but need a `require` call to activate their effects. You might see documentation like this: // 'require' call that doesn't use its return value var unused = require("magic-string-time"); /* or */ require("magic-string-time"); var x = "hello, world"; // Creates new methods on built-in types console.log(x.startsWithHello()); var y = [1, 2, 3]; // Creates new methods on built-in types console.log(y.reverseAndSort()); Here is an example // Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] // Project: [~THE PROJECT NAME~] // Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]> /*~ This is the global-modifying module template file. You should rename it to index.d.ts *~ and place it in a folder with the same name as the module. *~ For example, if you were writing a file for "super-greeter", this *~ file should be 'super-greeter/index.d.ts' */ /*~ Note: If your global-modifying module is callable or constructable, you'll *~ need to combine the patterns here with those in the module-class or module-function *~ template files */ declare global { /*~ Here, declare things that go in the global namespace, or augment *~ existing declarations in the global namespace */ interface String { fancyFormat(opts: StringFormatOptions): string; } } /*~ If your module exports types or values, write them as usual */ export interface StringFormatOptions { fancinessLevel: number; } /*~ For example, declaring a method on the module (in addition to its global side effects) */ export function doSomething(): void; /*~ If your module exports nothing, you'll need this line. Otherwise, delete it */ export {}; ##### On this page * Global-modifying Modules * Identifying global-modifying modules ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/declaration- files/templates/global-modifying-module.d.ts.md) ❤ Contributors to this page: MH OT 1+ Last updated: Mar 11, 2025 # Global: Plugin Was this page helpful? * Get Started * [TS for the New Programmer](../../typescript-from-scratch) * [TypeScript for JS Programmers](../../typescript-in-5-minutes) * [TS for Java/C# Programmers](../../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../../intro) * [The Basics](../../2/basic-types) * [Everyday Types](../../2/everyday-types) * [Narrowing](../../2/narrowing) * [More on Functions](../../2/functions) * [Object Types](../../2/objects) * Type Manipulation * [Creating Types from Types](../../2/types-from-types) * [Generics](../../2/generics) * [Keyof Type Operator](../../2/keyof-types) * [Typeof Type Operator](../../2/typeof-types) * [Indexed Access Types](../../2/indexed-access-types) * [Conditional Types](../../2/conditional-types) * [Mapped Types](../../2/mapped-types) * [Template Literal Types](../../2/template-literal-types) * [Classes](../../2/classes) * [Modules](../../2/modules) * Reference * [Utility Types](../../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../../decorators) * [Declaration Merging](../../declaration-merging) * [Enums](../../enums) * [Iterators and Generators](../../iterators-and-generators) * [JSX](../../jsx) * [Mixins](../../mixins) * [Namespaces](../../namespaces) * [Namespaces and Modules](../../namespaces-and-modules) * [Symbols](../../symbols) * [Triple-Slash Directives](../../triple-slash-directives) * [Type Compatibility](../../type-compatibility) * [Type Inference](../../type-inference) * [Variable Declaration](../../variable-declarations) * Modules Reference * [Introduction](../../modules/introduction) * [Theory](../../modules/theory) * Guides * [Choosing Compiler Options](../../modules/guides/choosing-compiler-options) * [Reference](../../modules/reference) * Appendices * [ESM/CJS Interoperability](../../modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../../asp-net-core) * [Gulp](../../gulp) * [DOM Manipulation](../../dom-manipulation) * [Migrating from JavaScript](../../migrating-from-javascript) * [Using Babel with TypeScript](../../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../introduction) * [Declaration Reference](../by-example) * [Library Structures](../library-structures) * .d.ts Templates * [Modules .d.ts](module-d-ts) * [Module: Plugin](module-plugin-d-ts) * [Module: Class](module-class-d-ts) * [Module: Function](module-function-d-ts) * [Global .d.ts](global-d-ts) * [Global: Modifying Module](global-modifying-module-d-ts) * [Do's and Don'ts](../do-s-and-don-ts) * [Deep Dive](../deep-dive) * [Publishing](../publishing) * [Consumption](../consumption) * JavaScript * [JS Projects Utilizing TypeScript](../../intro-to-js-ts) * [Type Checking JavaScript Files](../../type-checking-javascript-files) * [JSDoc Reference](../../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../dts-from-js) * Project Configuration * [What is a tsconfig.json](../../tsconfig-json) * [Compiler Options in MSBuild](../../compiler-options-in-msbuild) * [TSConfig Reference](../../../../tsconfig/index) * [tsc CLI Options](../../compiler-options) * [Project References](../../project-references) * [Integrating with Build Tools](../../integrating-with-build-tools) * [Configuring Watch](../../configuring-watch) * [Nightly Builds](../../nightly-builds) # Global: Plugin ## _UMD_ A _UMD_ module is one that can _either_ be used as module (through an import), or as a global (when run in an environment without a module loader). Many popular libraries, such as [Moment.js](http://momentjs.com/), are written this way. For example, in Node.js or using RequireJS, you would write: import moment = require("moment"); console.log(moment.format()); whereas in a vanilla browser environment you would write: console.log(moment.format()); ### Identifying a UMD library [UMD modules](https://github.com/umdjs/umd) check for the existence of a module loader environment. This is an easy-to-spot pattern that looks something like this: (function (root, factory) { if (typeof define === "function" && define.amd) { define(["libName"], factory); } else if (typeof module === "object" && module.exports) { module.exports = factory(require("libName")); } else { root.returnExports = factory(root.libName); } }(this, function (b) { If you see tests for `typeof define`, `typeof window`, or `typeof module` in the code of a library, especially at the top of the file, it’s almost always a UMD library. Documentation for UMD libraries will also often demonstrate a “Using in Node.js” example showing `require`, and a “Using in the browser” example showing using a ` Let’s explore a TypeScript script that adds a `

Hello, World!

` element to the `#app` element. // 1. Select the div element using the id property const app = document.getElementById("app"); // 2. Create a new

element programmatically const p = document.createElement("p"); // 3. Add the text content p.textContent = "Hello, World!"; // 4. Append the p element to the div element app?.appendChild(p); After compiling and running the _index.html_ page, the resulting HTML will be:

Hello, World!

## The `Document` Interface The first line of the TypeScript code uses a global variable `document`. Inspecting the variable shows it is defined by the `Document` interface from the _lib.dom.d.ts_ file. The code snippet contains calls to two methods, `getElementById` and `createElement`. ### `Document.getElementById` The definition for this method is as follows: getElementById(elementId: string): HTMLElement | null; Pass it an element id string and it will return either `HTMLElement` or `null`. This method introduces one of the most important types, `HTMLElement`. It serves as the base interface for every other element interface. For example, the `p` variable in the code example is of type `HTMLParagraphElement`. Also, take note that this method can return `null`. This is because the method can’t be certain pre-runtime if it will be able to actually find the specified element or not. In the last line of the code snippet, the new _optional chaining_ operator is used to call `appendChild`. ### `Document.createElement` The definition for this method is (I have omitted the _deprecated_ definition): createElement(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; createElement(tagName: string, options?: ElementCreationOptions): HTMLElement; This is an overloaded function definition. The second overload is simplest and works a lot like the `getElementById` method does. Pass it any `string` and it will return a standard HTMLElement. This definition is what enables developers to create unique HTML element tags. For example `document.createElement('xyz')` returns a `` element, clearly not an element that is specified by the HTML specification. > For those interested, you can interact with custom tag elements using the > `document.getElementsByTagName` For the first definition of `createElement`, it is using some advanced generic patterns. It is best understood broken down into chunks, starting with the generic expression: ``. This expression defines a generic parameter `K` that is _constrained_ to the keys of the interface `HTMLElementTagNameMap`. The map interface contains every specified HTML tag name and its corresponding type interface. For example here are the first 5 mapped values: interface HTMLElementTagNameMap { "a": HTMLAnchorElement; "abbr": HTMLElement; "address": HTMLElement; "applet": HTMLAppletElement; "area": HTMLAreaElement; ... } Some elements do not exhibit unique properties and so they just return `HTMLElement`, but other types do have unique properties and methods so they return their specific interface (which will extend from or implement `HTMLElement`). Now, for the remainder of the `createElement` definition: `(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]`. The first argument `tagName` is defined as the generic parameter `K`. The TypeScript interpreter is smart enough to _infer_ the generic parameter from this argument. This means that the developer does not have to specify the generic parameter when using the method; whatever value is passed to the `tagName` argument will be inferred as `K` and thus can be used throughout the remainder of the definition. This is exactly what happens; the return value `HTMLElementTagNameMap[K]` takes the `tagName` argument and uses it to return the corresponding type. This definition is how the `p` variable from the code snippet gets a type of `HTMLParagraphElement`. And if the code was `document.createElement('a')`, then it would be an element of type `HTMLAnchorElement`. ## The `Node` interface The `document.getElementById` function returns an `HTMLElement`. `HTMLElement` interface extends the `Element` interface which extends the `Node` interface. This prototypal extension allows for all `HTMLElements` to utilize a subset of standard methods. In the code snippet, we use a property defined on the `Node` interface to append the new `p` element to the website. ### `Node.appendChild` The last line of the code snippet is `app?.appendChild(p)`. The previous, `document.getElementById`, section detailed that the _optional chaining_ operator is used here because `app` can potentially be null at runtime. The `appendChild` method is defined by: appendChild(newChild: T): T; This method works similarly to the `createElement` method as the generic parameter `T` is inferred from the `newChild` argument. `T` is _constrained_ to another base interface `Node`. ## Difference between `children` and `childNodes` Previously, this document details the `HTMLElement` interface extends from `Element` which extends from `Node`. In the DOM API there is a concept of _children_ elements. For example in the following HTML, the `p` tags are children of the `div` element

Hello, World

TypeScript!

; const div = document.getElementsByTagName("div")[0]; div.children; // HTMLCollection(2) [p, p] div.childNodes; // NodeList(2) [p, p] After capturing the `div` element, the `children` prop will return an `HTMLCollection` list containing the `HTMLParagraphElements`. The `childNodes` property will return a similar `NodeList` list of nodes. Each `p` tag will still be of type `HTMLParagraphElements`, but the `NodeList` can contain additional _HTML nodes_ that the `HTMLCollection` list cannot. Modify the HTML by removing one of the `p` tags, but keep the text.

Hello, World

TypeScript!
; const div = document.getElementsByTagName("div")[0]; div.children; // HTMLCollection(1) [p] div.childNodes; // NodeList(2) [p, text] See how both lists change. `children` now only contains the `

Hello, World

` element, and the `childNodes` contains a `text` node rather than two `p` nodes. The `text` part of the `NodeList` is the literal `Node` containing the text `TypeScript!`. The `children` list does not contain this `Node` because it is not considered an `HTMLElement`. ## The `querySelector` and `querySelectorAll` methods Both of these methods are great tools for getting lists of dom elements that fit a more unique set of constraints. They are defined in _lib.dom.d.ts_ as: /** * Returns the first element that is a descendant of node that matches selectors. */ querySelector(selectors: K): HTMLElementTagNameMap[K] | null; querySelector(selectors: K): SVGElementTagNameMap[K] | null; querySelector(selectors: string): E | null; /** * Returns all element descendants of node that match selectors. */ querySelectorAll(selectors: K): NodeListOf; querySelectorAll(selectors: K): NodeListOf; querySelectorAll(selectors: string): NodeListOf; The `querySelectorAll` definition is similar to `getElementsByTagName`, except it returns a new type: `NodeListOf`. This return type is essentially a custom implementation of the standard JavaScript list element. Arguably, replacing `NodeListOf` with `E[]` would result in a very similar user experience. `NodeListOf` only implements the following properties and methods: `length`, `item(index)`, `forEach((value, key, parent) => void)`, and numeric indexing. Additionally, this method returns a list of _elements_ , not _nodes_ , which is what `NodeList` was returning from the `.childNodes` method. While this may appear as a discrepancy, take note that interface `Element` extends from `Node`. To see these methods in action modify the existing code to:
  • First :)
  • Second!
  • Third times a charm.
; const first = document.querySelector("li"); // returns the first li element const all = document.querySelectorAll("li"); // returns the list of all li elements ## Interested in learning more? The best part about the _lib.dom.d.ts_ type definitions is that they are reflective of the types annotated in the Mozilla Developer Network (MDN) documentation site. For example, the `HTMLElement` interface is documented by this [HTMLElement page](https://developer.mozilla.org/docs/Web/API/HTMLElement) on MDN. These pages list all available properties, methods, and sometimes even examples. Another great aspect of the pages is that they provide links to the corresponding standard documents. Here is the link to the [W3C Recommendation for HTMLElement](https://www.w3.org/TR/html52/dom.html#htmlelement). Sources: * [ECMA-262 Standard](http://www.ecma-international.org/ecma-262/10.0/index.html) * [Introduction to the DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) ##### On this page * DOM Manipulation * An exploration into the HTMLElement type * Basic Example * The Document Interface * Document.getElementById * Document.createElement * The Node interface * Node.appendChild * Difference between children and childNodes * The querySelector and querySelectorAll methods * Interested in learning more? ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/tutorials/DOM%20Manipulation.md) ❤ Contributors to this page: EA OT SA M IO 6+ Last updated: Mar 11, 2025 # Enums Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) # Enums Enums are one of the few features TypeScript has which is not a type-level extension of JavaScript. Enums allow a developer to define a set of named constants. Using enums can make it easier to document intent, or create a set of distinct cases. TypeScript provides both numeric and string-based enums. ## Numeric enums We’ll first start off with numeric enums, which are probably more familiar if you’re coming from other languages. An enum can be defined using the `enum` keyword. enum Direction { Up = 1, Down, Left, Right, } Above, we have a numeric enum where `Up` is initialized with `1`. All of the following members are auto-incremented from that point on. In other words, `Direction.Up` has the value `1`, `Down` has `2`, `Left` has `3`, and `Right` has `4`. If we wanted, we could leave off the initializers entirely: enum Direction { Up, Down, Left, Right, } Here, `Up` would have the value `0`, `Down` would have `1`, etc. This auto- incrementing behavior is useful for cases where we might not care about the member values themselves, but do care that each value is distinct from other values in the same enum. Using an enum is simple: just access any member as a property off of the enum itself, and declare types using the name of the enum: enum UserResponse { No = 0, Yes = 1, }   function respond(recipient: string, message: UserResponse): void { // ... }   respond("Princess Caroline", UserResponse.Yes); Numeric enums can be mixed in computed and constant members (see below). The short story is, enums without initializers either need to be first, or have to come after numeric enums initialized with numeric constants or other constant enum members. In other words, the following isn’t allowed: enum E { A = getSomeValue(), B, } ## String enums String enums are a similar concept, but have some subtle runtime differences as documented below. In a string enum, each member has to be constant- initialized with a string literal, or with another string enum member. enum Direction { Up = "UP", Down = "DOWN", Left = "LEFT", Right = "RIGHT", } While string enums don’t have auto-incrementing behavior, string enums have the benefit that they “serialize” well. In other words, if you were debugging and had to read the runtime value of a numeric enum, the value is often opaque - it doesn’t convey any useful meaning on its own (though reverse mapping can often help). String enums allow you to give a meaningful and readable value when your code runs, independent of the name of the enum member itself. ## Heterogeneous enums Technically enums can be mixed with string and numeric members, but it’s not clear why you would ever want to do so: enum BooleanLikeHeterogeneousEnum { No = 0, Yes = "YES", } Unless you’re really trying to take advantage of JavaScript’s runtime behavior in a clever way, it’s advised that you don’t do this. ## Computed and constant members Each enum member has a value associated with it which can be either _constant_ or _computed_. An enum member is considered constant if: * It is the first member in the enum and it has no initializer, in which case it’s assigned the value `0`: // E.X is constant: enum E { X, } * It does not have an initializer and the preceding enum member was a _numeric_ constant. In this case the value of the current enum member will be the value of the preceding enum member plus one. // All enum members in 'E1' and 'E2' are constant.   enum E1 { X, Y, Z, }   enum E2 { A = 1, B, C, } * The enum member is initialized with a constant enum expression. A constant enum expression is a subset of TypeScript expressions that can be fully evaluated at compile time. An expression is a constant enum expression if it is: 1. a literal enum expression (basically a string literal or a numeric literal) 2. a reference to previously defined constant enum member (which can originate from a different enum) 3. a parenthesized constant enum expression 4. one of the `+`, `-`, `~` unary operators applied to constant enum expression 5. `+`, `-`, `*`, `/`, `%`, `<<`, `>>`, `>>>`, `&`, `|`, `^` binary operators with constant enum expressions as operands It is a compile time error for constant enum expressions to be evaluated to `NaN` or `Infinity`. In all other cases enum member is considered computed. enum FileAccess { // constant members None, Read = 1 << 1, Write = 1 << 2, ReadWrite = Read | Write, // computed member G = "123".length, } ## Union enums and enum member types There is a special subset of constant enum members that aren’t calculated: literal enum members. A literal enum member is a constant enum member with no initialized value, or with values that are initialized to * any string literal (e.g. `"foo"`, `"bar"`, `"baz"`) * any numeric literal (e.g. `1`, `100`) * a unary minus applied to any numeric literal (e.g. `-1`, `-100`) When all members in an enum have literal enum values, some special semantics come into play. The first is that enum members also become types as well! For example, we can say that certain members can _only_ have the value of an enum member: enum ShapeKind { Circle, Square, }   interface Circle { kind: ShapeKind.Circle; radius: number; }   interface Square { kind: ShapeKind.Square; sideLength: number; }   let c: Circle = { kind: ShapeKind.Square, radius: 100, }; The other change is that enum types themselves effectively become a _union_ of each enum member. With union enums, the type system is able to leverage the fact that it knows the exact set of values that exist in the enum itself. Because of that, TypeScript can catch bugs where we might be comparing values incorrectly. For example: enum E { Foo, Bar, }   function f(x: E) { if (x !== E.Foo || x !== E.Bar) { // } } In that example, we first checked whether `x` was _not_ `E.Foo`. If that check succeeds, then our `||` will short-circuit, and the body of the ‘if’ will run. However, if the check didn’t succeed, then `x` can _only_ be `E.Foo`, so it doesn’t make sense to see whether it’s _not_ equal to `E.Bar`. ## Enums at runtime Enums are real objects that exist at runtime. For example, the following enum enum E { X, Y, Z, } can actually be passed around to functions enum E { X, Y, Z, }   function f(obj: { X: number }) { return obj.X; }   // Works, since 'E' has a property named 'X' which is a number. f(E); ## Enums at compile time Even though Enums are real objects that exist at runtime, the `keyof` keyword works differently than you might expect for typical objects. Instead, use `keyof typeof` to get a Type that represents all Enum keys as strings. enum LogLevel { ERROR, WARN, INFO, DEBUG, }   /** * This is equivalent to: * type LogLevelStrings = 'ERROR' | 'WARN' | 'INFO' | 'DEBUG'; */ type LogLevelStrings = keyof typeof LogLevel;   function printImportant(key: LogLevelStrings, message: string) { const num = LogLevel[key]; if (num <= LogLevel.WARN) { console.log("Log level key is:", key); console.log("Log level value is:", num); console.log("Log level message is:", message); } } printImportant("ERROR", "This is a message"); ### Reverse mappings In addition to creating an object with property names for members, numeric enums members also get a _reverse mapping_ from enum values to enum names. For example, in this example: enum Enum { A, }   let a = Enum.A; let nameOfA = Enum[a]; // "A" TypeScript compiles this down to the following JavaScript: "use strict"; var Enum; (function (Enum) { Enum[Enum["A"] = 0] = "A"; })(Enum || (Enum = {})); let a = Enum.A; let nameOfA = Enum[a]; // "A"   In this generated code, an enum is compiled into an object that stores both forward (`name` -> `value`) and reverse (`value` -> `name`) mappings. References to other enum members are always emitted as property accesses and never inlined. Keep in mind that string enum members _do not_ get a reverse mapping generated at all. ### `const` enums In most cases, enums are a perfectly valid solution. However sometimes requirements are tighter. To avoid paying the cost of extra generated code and additional indirection when accessing enum values, it’s possible to use `const` enums. Const enums are defined using the `const` modifier on our enums: const enum Enum { A = 1, B = A * 2, } Const enums can only use constant enum expressions and unlike regular enums they are completely removed during compilation. Const enum members are inlined at use sites. This is possible since const enums cannot have computed members. const enum Direction { Up, Down, Left, Right, }   let directions = [ Direction.Up, Direction.Down, Direction.Left, Direction.Right, ]; in generated code will become "use strict"; let directions = [ 0 /* Direction.Up */, 1 /* Direction.Down */, 2 /* Direction.Left */, 3 /* Direction.Right */, ];   #### Const enum pitfalls Inlining enum values is straightforward at first, but comes with subtle implications. These pitfalls pertain to _ambient_ const enums only (basically const enums in `.d.ts` files) and sharing them between projects, but if you are publishing or consuming `.d.ts` files, these pitfalls likely apply to you, because `tsc --declaration` transforms `.ts` files into `.d.ts` files. 1. For the reasons laid out in the [`isolatedModules` documentation](../../tsconfig#references-to-const-enum-members), that mode is fundamentally incompatible with ambient const enums. This means if you publish ambient const enums, downstream consumers will not be able to use [`isolatedModules`](../../tsconfig#isolatedModules) and those enum values at the same time. 2. You can easily inline values from version A of a dependency at compile time, and import version B at runtime. Version A and B’s enums can have different values, if you are not very careful, resulting in [surprising bugs](https://github.com/microsoft/TypeScript/issues/5219#issue-110947903), like taking the wrong branches of `if` statements. These bugs are especially pernicious because it is common to run automated tests at roughly the same time as projects are built, with the same dependency versions, which misses these bugs completely. 3. [`importsNotUsedAsValues: "preserve"`](../../tsconfig#importsNotUsedAsValues) will not elide imports for const enums used as values, but ambient const enums do not guarantee that runtime `.js` files exist. The unresolvable imports cause errors at runtime. The usual way to unambiguously elide imports, [type-only imports](modules/reference#type-only-imports-and-exports), [does not allow const enum values](https://github.com/microsoft/TypeScript/issues/40344), currently. Here are two approaches to avoiding these pitfalls: 1. Do not use const enums at all. You can easily [ban const enums](https://typescript-eslint.io/linting/troubleshooting#how-can-i-ban-specific-language-feature) with the help of a linter. Obviously this avoids any issues with const enums, but prevents your project from inlining its own enums. Unlike inlining enums from other projects, inlining a project’s own enums is not problematic and has performance implications. 2. Do not publish ambient const enums, by deconstifying them with the help of [`preserveConstEnums`](../../tsconfig#preserveConstEnums). This is the approach taken internally by the [TypeScript project itself](https://github.com/microsoft/TypeScript/pull/5422). [`preserveConstEnums`](../../tsconfig#preserveConstEnums) emits the same JavaScript for const enums as plain enums. You can then safely strip the `const` modifier from `.d.ts` files [in a build step](https://github.com/microsoft/TypeScript/blob/1a981d1df1810c868a66b3828497f049a944951c/Gulpfile.js#L144). This way downstream consumers will not inline enums from your project, avoiding the pitfalls above, but a project can still inline its own enums, unlike banning const enums entirely. ## Ambient enums Ambient enums are used to describe the shape of already existing enum types. declare enum Enum { A = 1, B, C = 2, } One important difference between ambient and non-ambient enums is that, in regular enums, members that don’t have an initializer will be considered constant if its preceding enum member is considered constant. By contrast, an ambient (and non-const) enum member that does not have an initializer is _always_ considered computed. ## Objects vs Enums In modern TypeScript, you may not need an enum when an object with `as const` could suffice: const enum EDirection { Up, Down, Left, Right, }   const ODirection = { Up: 0, Down: 1, Left: 2, Right: 3, } as const;   EDirection.Up;   ODirection.Up;   // Using the enum as a parameter function walk(dir: EDirection) {}   // It requires an extra line to pull out the values type Direction = typeof ODirection[keyof typeof ODirection]; function run(dir: Direction) {}   walk(EDirection.Left); run(ODirection.Right); The biggest argument in favour of this format over TypeScript’s `enum` is that it keeps your codebase aligned with the state of JavaScript, and [when/if](https://github.com/rbuckton/proposal-enum) enums are added to JavaScript then you can move to the additional syntax. ##### On this page * Numeric enums * String enums * Heterogeneous enums * Computed and constant members * Union enums and enum member types * Enums at runtime * Enums at compile time * Reverse mappings * const enums * Ambient enums * Objects vs Enums ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/reference/Enums.md) ❤ Contributors to this page: OT AG FDG-S G TA 11+ Last updated: Mar 11, 2025 # Functions Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) ### This page has been deprecated This handbook page has been replaced, [go to the new page](2/functions) [Go to new page](2/functions) # Functions Functions are the fundamental building block of any application in JavaScript. They’re how you build up layers of abstraction, mimicking classes, information hiding, and modules. In TypeScript, while there are classes, namespaces, and modules, functions still play the key role in describing how to _do_ things. TypeScript also adds some new capabilities to the standard JavaScript functions to make them easier to work with. ## Functions To begin, just as in JavaScript, TypeScript functions can be created both as a named function or as an anonymous function. This allows you to choose the most appropriate approach for your application, whether you’re building a list of functions in an API or a one-off function to hand off to another function. To quickly recap what these two approaches look like in JavaScript: // Named function function add(x, y) { return x + y; }   // Anonymous function let myAdd = function (x, y) { return x + y; }; Just as in JavaScript, functions can refer to variables outside of the function body. When they do so, they’re said to _capture_ these variables. While understanding how this works (and the trade-offs when using this technique) is outside of the scope of this article, having a firm understanding how this mechanic works is an important piece of working with JavaScript and TypeScript. let z = 100;   function addToZ(x, y) { return x + y + z; } ## Function Types ### Typing the function Let’s add types to our simple examples from earlier: function add(x: number, y: number): number { return x + y; }   let myAdd = function (x: number, y: number): number { return x + y; }; We can add types to each of the parameters and then to the function itself to add a return type. TypeScript can figure the return type out by looking at the return statements, so we can also optionally leave this off in many cases. ### Writing the function type Now that we’ve typed the function, let’s write the full type of the function out by looking at each piece of the function type. let myAdd: (x: number, y: number) => number = function ( x: number, y: number ): number { return x + y; }; A function’s type has the same two parts: the type of the arguments and the return type. When writing out the whole function type, both parts are required. We write out the parameter types just like a parameter list, giving each parameter a name and a type. This name is just to help with readability. We could have instead written: let myAdd: (baseValue: number, increment: number) => number = function ( x: number, y: number ): number { return x + y; }; As long as the parameter types line up, it’s considered a valid type for the function, regardless of the names you give the parameters in the function type. The second part is the return type. We make it clear which is the return type by using an arrow (`=>`) between the parameters and the return type. As mentioned before, this is a required part of the function type, so if the function doesn’t return a value, you would use `void` instead of leaving it off. Of note, only the parameters and the return type make up the function type. Captured variables are not reflected in the type. In effect, captured variables are part of the “hidden state” of any function and do not make up its API. ### Inferring the types In playing with the example, you may notice that the TypeScript compiler can figure out the type even if you only have types on one side of the equation: // The parameters 'x' and 'y' have the type number let myAdd = function (x: number, y: number): number { return x + y; };   // myAdd has the full function type let myAdd2: (baseValue: number, increment: number) => number = function (x, y) { return x + y; }; This is called “contextual typing”, a form of type inference. This helps cut down on the amount of effort to keep your program typed. ## Optional and Default Parameters In TypeScript, every parameter is assumed to be required by the function. This doesn’t mean that it can’t be given `null` or `undefined`, but rather, when the function is called, the compiler will check that the user has provided a value for each parameter. The compiler also assumes that these parameters are the only parameters that will be passed to the function. In short, the number of arguments given to a function has to match the number of parameters the function expects. function buildName(firstName: string, lastName: string) { return firstName + " " + lastName; }   let result1 = buildName("Bob"); // error, too few parameters let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters let result3 = buildName("Bob", "Adams"); // ah, just right In JavaScript, every parameter is optional, and users may leave them off as they see fit. When they do, their value is `undefined`. We can get this functionality in TypeScript by adding a `?` to the end of parameters we want to be optional. For example, let’s say we want the last name parameter from above to be optional: function buildName(firstName: string, lastName?: string) { if (lastName) return firstName + " " + lastName; else return firstName; }   let result1 = buildName("Bob"); // works correctly now let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters let result3 = buildName("Bob", "Adams"); // ah, just right Any optional parameters must follow required parameters. Had we wanted to make the first name optional, rather than the last name, we would need to change the order of parameters in the function, putting the first name last in the list. In TypeScript, we can also set a value that a parameter will be assigned if the user does not provide one, or if the user passes `undefined` in its place. These are called default-initialized parameters. Let’s take the previous example and default the last name to `"Smith"`. function buildName(firstName: string, lastName = "Smith") { return firstName + " " + lastName; }   let result1 = buildName("Bob"); // works correctly now, returns "Bob Smith" let result2 = buildName("Bob", undefined); // still works, also returns "Bob Smith" let result3 = buildName("Bob", "Adams", "Sr."); // error, too many parameters let result4 = buildName("Bob", "Adams"); // ah, just right Default-initialized parameters that come after all required parameters are treated as optional, and just like optional parameters, can be omitted when calling their respective function. This means optional parameters and trailing default parameters will share commonality in their types, so both function buildName(firstName: string, lastName?: string) { // ... } and function buildName(firstName: string, lastName = "Smith") { // ... } share the same type `(firstName: string, lastName?: string) => string`. The default value of `lastName` disappears in the type, only leaving behind the fact that the parameter is optional. Unlike plain optional parameters, default-initialized parameters don’t _need_ to occur after required parameters. If a default-initialized parameter comes before a required parameter, users need to explicitly pass `undefined` to get the default initialized value. For example, we could write our last example with only a default initializer on `firstName`: function buildName(firstName = "Will", lastName: string) { return firstName + " " + lastName; }   let result1 = buildName("Bob"); // error, too few parameters let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters let result3 = buildName("Bob", "Adams"); // okay and returns "Bob Adams" let result4 = buildName(undefined, "Adams"); // okay and returns "Will Adams" ### Rest Parameters Required, optional, and default parameters all have one thing in common: they talk about one parameter at a time. Sometimes, you want to work with multiple parameters as a group, or you may not know how many parameters a function will ultimately take. In JavaScript, you can work with the arguments directly using the `arguments` variable that is visible inside every function body. In TypeScript, you can gather these arguments together into a variable: function buildName(firstName: string, ...restOfName: string[]) { return firstName + " " + restOfName.join(" "); }   // employeeName will be "Joseph Samuel Lucas MacKinzie" let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie"); _Rest parameters_ are treated as a boundless number of optional parameters. When passing arguments for a rest parameter, you can use as many as you want; you can even pass none. The compiler will build an array of the arguments passed in with the name given after the ellipsis (`...`), allowing you to use it in your function. The ellipsis is also used in the type of the function with rest parameters: function buildName(firstName: string, ...restOfName: string[]) { return firstName + " " + restOfName.join(" "); }   let buildNameFun: (fname: string, ...rest: string[]) => string = buildName; ## `this` Learning how to use `this` in JavaScript is something of a rite of passage. Since TypeScript is a superset of JavaScript, TypeScript developers also need to learn how to use `this` and how to spot when it’s not being used correctly. Fortunately, TypeScript lets you catch incorrect uses of `this` with a couple of techniques. If you need to learn how `this` works in JavaScript, though, first read Yehuda Katz’s [Understanding JavaScript Function Invocation and “this”](http://yehudakatz.com/2011/08/11/understanding-javascript-function- invocation-and-this/). Yehuda’s article explains the inner workings of `this` very well, so we’ll just cover the basics here. ### `this` and arrow functions In JavaScript, `this` is a variable that’s set when a function is called. This makes it a very powerful and flexible feature, but it comes at the cost of always having to know about the context that a function is executing in. This is notoriously confusing, especially when returning a function or passing a function as an argument. Let’s look at an example: let deck = { suits: ["hearts", "spades", "clubs", "diamonds"], cards: Array(52), createCardPicker: function () { return function () { let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13);   return { suit: this.suits[pickedSuit], card: pickedCard % 13 }; }; }, };   let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker();   alert("card: " + pickedCard.card + " of " + pickedCard.suit); Notice that `createCardPicker` is a function that itself returns a function. If we tried to run the example, we would get an error instead of the expected alert box. This is because the `this` being used in the function created by `createCardPicker` will be set to `window` instead of our `deck` object. That’s because we call `cardPicker()` on its own. A top-level non-method syntax call like this will use `window` for `this`. (Note: under strict mode, `this` will be `undefined` rather than `window`). We can fix this by making sure the function is bound to the correct `this` before we return the function to be used later. This way, regardless of how it’s later used, it will still be able to see the original `deck` object. To do this, we change the function expression to use the ECMAScript 6 arrow syntax. Arrow functions capture the `this` where the function is created rather than where it is invoked: let deck = { suits: ["hearts", "spades", "clubs", "diamonds"], cards: Array(52), createCardPicker: function () { // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here return () => { let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13);   return { suit: this.suits[pickedSuit], card: pickedCard % 13 }; }; }, };   let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker();   alert("card: " + pickedCard.card + " of " + pickedCard.suit); Even better, TypeScript will warn you when you make this mistake if you pass the [`noImplicitThis`](../../tsconfig#noImplicitThis) flag to the compiler. It will point out that `this` in `this.suits[pickedSuit]` is of type `any`. ### `this` parameters Unfortunately, the type of `this.suits[pickedSuit]` is still `any`. That’s because `this` comes from the function expression inside the object literal. To fix this, you can provide an explicit `this` parameter. `this` parameters are fake parameters that come first in the parameter list of a function: function f(this: void) { // make sure `this` is unusable in this standalone function } Let’s add a couple of interfaces to our example above, `Card` and `Deck`, to make the types clearer and easier to reuse: interface Card { suit: string; card: number; }   interface Deck { suits: string[]; cards: number[]; createCardPicker(this: Deck): () => Card; }   let deck: Deck = { suits: ["hearts", "spades", "clubs", "diamonds"], cards: Array(52), // NOTE: The function now explicitly specifies that its callee must be of type Deck createCardPicker: function (this: Deck) { return () => { let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13);   return { suit: this.suits[pickedSuit], card: pickedCard % 13 }; }; }, };   let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker();   alert("card: " + pickedCard.card + " of " + pickedCard.suit); Now TypeScript knows that `createCardPicker` expects to be called on a `Deck` object. That means that `this` is of type `Deck` now, not `any`, so [`noImplicitThis`](../../tsconfig#noImplicitThis) will not cause any errors. #### `this` parameters in callbacks You can also run into errors with `this` in callbacks, when you pass functions to a library that will later call them. Because the library that calls your callback will call it like a normal function, `this` will be `undefined`. With some work you can use `this` parameters to prevent errors with callbacks too. First, the library author needs to annotate the callback type with `this`: interface UIElement { addClickListener(onclick: (this: void, e: Event) => void): void; } `this: void` means that `addClickListener` expects `onclick` to be a function that does not require a `this` type. Second, annotate your calling code with `this`: class Handler { info: string; onClickBad(this: Handler, e: Event) { // oops, used `this` here. using this callback would crash at runtime this.info = e.message; } }   let h = new Handler(); uiElement.addClickListener(h.onClickBad); // error! With `this` annotated, you make it explicit that `onClickBad` must be called on an instance of `Handler`. Then TypeScript will detect that `addClickListener` requires a function that has `this: void`. To fix the error, change the type of `this`: class Handler { info: string; onClickGood(this: void, e: Event) { // can't use `this` here because it's of type void! console.log("clicked!"); } }   let h = new Handler(); uiElement.addClickListener(h.onClickGood); Because `onClickGood` specifies its `this` type as `void`, it is legal to pass to `addClickListener`. Of course, this also means that it can’t use `this.info`. If you want both then you’ll have to use an arrow function: class Handler { info: string; onClickGood = (e: Event) => { this.info = e.message; }; } This works because arrow functions use the outer `this`, so you can always pass them to something that expects `this: void`. The downside is that one arrow function is created per object of type Handler. Methods, on the other hand, are only created once and attached to Handler’s prototype. They are shared between all objects of type Handler. ## Overloads JavaScript is inherently a very dynamic language. It’s not uncommon for a single JavaScript function to return different types of objects based on the shape of the arguments passed in. let suits = ["hearts", "spades", "clubs", "diamonds"];   function pickCard(x: any): any { // Check to see if we're working with an object/array // if so, they gave us the deck and we'll pick the card if (typeof x == "object") { let pickedCard = Math.floor(Math.random() * x.length); return pickedCard; } // Otherwise just let them pick the card else if (typeof x == "number") { let pickedSuit = Math.floor(x / 13); return { suit: suits[pickedSuit], card: x % 13 }; } }   let myDeck = [ { suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }, ];   let pickedCard1 = myDeck[pickCard(myDeck)]; alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);   let pickedCard2 = pickCard(15); alert("card: " + pickedCard2.card + " of " + pickedCard2.suit); Here, the `pickCard` function will return two different things based on what the user has passed in. If the users passes in an object that represents the deck, the function will pick the card. If the user picks the card, we tell them which card they’ve picked. But how do we describe this to the type system? The answer is to supply multiple function types for the same function as a list of overloads. This list is what the compiler will use to resolve function calls. Let’s create a list of overloads that describe what our `pickCard` accepts and what it returns. let suits = ["hearts", "spades", "clubs", "diamonds"];   function pickCard(x: { suit: string; card: number }[]): number; function pickCard(x: number): { suit: string; card: number }; function pickCard(x: any): any { // Check to see if we're working with an object/array // if so, they gave us the deck and we'll pick the card if (typeof x == "object") { let pickedCard = Math.floor(Math.random() * x.length); return pickedCard; } // Otherwise just let them pick the card else if (typeof x == "number") { let pickedSuit = Math.floor(x / 13); return { suit: suits[pickedSuit], card: x % 13 }; } }   let myDeck = [ { suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }, ];   let pickedCard1 = myDeck[pickCard(myDeck)]; alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);   let pickedCard2 = pickCard(15); alert("card: " + pickedCard2.card + " of " + pickedCard2.suit); With this change, the overloads now give us type checked calls to the `pickCard` function. In order for the compiler to pick the correct type check, it follows a similar process to the underlying JavaScript. It looks at the overload list and, proceeding with the first overload, attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload. For this reason, it’s customary to order overloads from most specific to least specific. Note that the `function pickCard(x): any` piece is not part of the overload list, so it only has two overloads: one that takes an object and one that takes a number. Calling `pickCard` with any other parameter types would cause an error. ##### On this page * Functions * Function Types * Typing the function * Writing the function type * Inferring the types * Optional and Default Parameters * Rest Parameters * this * this and arrow functions * this parameters * Overloads ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v1/Functions.md) ❤ Contributors to this page: RC DR OT NS MF 24+ Last updated: Mar 11, 2025 # Generics Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) ### This page has been deprecated This handbook page has been replaced, [go to the new page](2/generics) [Go to new page](2/generics) # Generics A major part of software engineering is building components that not only have well-defined and consistent APIs, but are also reusable. Components that are capable of working on the data of today as well as the data of tomorrow will give you the most flexible capabilities for building up large software systems. In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is _generics_ , that is, being able to create a component that can work over a variety of types rather than a single one. This allows users to consume these components and use their own types. ## Hello World of Generics To start off, let’s do the “hello world” of generics: the identity function. The identity function is a function that will return back whatever is passed in. You can think of this in a similar way to the `echo` command. Without generics, we would either have to give the identity function a specific type: function identity(arg: number): number { return arg; } Or, we could describe the identity function using the `any` type: function identity(arg: any): any { return arg; } While using `any` is certainly generic in that it will cause the function to accept any and all types for the type of `arg`, we actually are losing the information about what that type was when the function returns. If we passed in a number, the only information we have is that any type could be returned. Instead, we need a way of capturing the type of the argument in such a way that we can also use it to denote what is being returned. Here, we will use a _type variable_ , a special kind of variable that works on types rather than values. function identity(arg: T): T { return arg; } We’ve now added a type variable `T` to the identity function. This `T` allows us to capture the type the user provides (e.g. `number`), so that we can use that information later. Here, we use `T` again as the return type. On inspection, we can now see the same type is used for the argument and the return type. This allows us to traffic that type information in one side of the function and out the other. We say that this version of the `identity` function is generic, as it works over a range of types. Unlike using `any`, it’s also just as precise (ie, it doesn’t lose any information) as the first `identity` function that used numbers for the argument and return type. Once we’ve written the generic identity function, we can call it in one of two ways. The first way is to pass all of the arguments, including the type argument, to the function: let output = identity("myString"); Here we explicitly set `T` to be `string` as one of the arguments to the function call, denoted using the `<>` around the arguments rather than `()`. The second way is also perhaps the most common. Here we use _type argument inference_ — that is, we want the compiler to set the value of `T` for us automatically based on the type of the argument we pass in: let output = identity("myString"); Notice that we didn’t have to explicitly pass the type in the angle brackets (`<>`); the compiler just looked at the value `"myString"`, and set `T` to its type. While type argument inference can be a helpful tool to keep code shorter and more readable, you may need to explicitly pass in the type arguments as we did in the previous example when the compiler fails to infer the type, as may happen in more complex examples. ## Working with Generic Type Variables When you begin to use generics, you’ll notice that when you create generic functions like `identity`, the compiler will enforce that you use any generically typed parameters in the body of the function correctly. That is, that you actually treat these parameters as if they could be any and all types. Let’s take our `identity` function from earlier: function identity(arg: T): T { return arg; } What if we want to also log the length of the argument `arg` to the console with each call? We might be tempted to write this: function loggingIdentity(arg: T): T { console.log(arg.length); return arg; } When we do, the compiler will give us an error that we’re using the `.length` member of `arg`, but nowhere have we said that `arg` has this member. Remember, we said earlier that these type variables stand in for any and all types, so someone using this function could have passed in a `number` instead, which does not have a `.length` member. Let’s say that we’ve actually intended this function to work on arrays of `T` rather than `T` directly. Since we’re working with arrays, the `.length` member should be available. We can describe this just like we would create arrays of other types: function loggingIdentity(arg: T[]): T[] { console.log(arg.length); return arg; } You can read the type of `loggingIdentity` as “the generic function `loggingIdentity` takes a type parameter `T`, and an argument `arg` which is an array of `T`s, and returns an array of `T`s.” If we passed in an array of numbers, we’d get an array of numbers back out, as `T` would bind to `number`. This allows us to use our generic type variable `T` as part of the types we’re working with, rather than the whole type, giving us greater flexibility. We can alternatively write the sample example this way: function loggingIdentity(arg: Array): Array { console.log(arg.length); // Array has a .length, so no more error return arg; } You may already be familiar with this style of type from other languages. In the next section, we’ll cover how you can create your own generic types like `Array`. ## Generic Types In previous sections, we created generic identity functions that worked over a range of types. In this section, we’ll explore the type of the functions themselves and how to create generic interfaces. The type of generic functions is just like those of non-generic functions, with the type parameters listed first, similarly to function declarations: function identity(arg: T): T { return arg; }   let myIdentity: (arg: T) => T = identity; We could also have used a different name for the generic type parameter in the type, so long as the number of type variables and how the type variables are used line up. function identity(arg: T): T { return arg; }   let myIdentity: (arg: U) => U = identity; We can also write the generic type as a call signature of an object literal type: function identity(arg: T): T { return arg; }   let myIdentity: { (arg: T): T } = identity; Which leads us to writing our first generic interface. Let’s take the object literal from the previous example and move it to an interface: interface GenericIdentityFn { (arg: T): T; }   function identity(arg: T): T { return arg; }   let myIdentity: GenericIdentityFn = identity; In a similar example, we may want to move the generic parameter to be a parameter of the whole interface. This lets us see what type(s) we’re generic over (e.g. `Dictionary` rather than just `Dictionary`). This makes the type parameter visible to all the other members of the interface. interface GenericIdentityFn { (arg: T): T; }   function identity(arg: T): T { return arg; }   let myIdentity: GenericIdentityFn = identity; Notice that our example has changed to be something slightly different. Instead of describing a generic function, we now have a non-generic function signature that is a part of a generic type. When we use `GenericIdentityFn`, we now will also need to specify the corresponding type argument (here: `number`), effectively locking in what the underlying call signature will use. Understanding when to put the type parameter directly on the call signature and when to put it on the interface itself will be helpful in describing what aspects of a type are generic. In addition to generic interfaces, we can also create generic classes. Note that it is not possible to create generic enums and namespaces. ## Generic Classes A generic class has a similar shape to a generic interface. Generic classes have a generic type parameter list in angle brackets (`<>`) following the name of the class. class GenericNumber { zeroValue: T; add: (x: T, y: T) => T; }   let myGenericNumber = new GenericNumber(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function (x, y) { return x + y; }; This is a pretty literal use of the `GenericNumber` class, but you may have noticed that nothing is restricting it to only use the `number` type. We could have instead used `string` or even more complex objects. let stringNumeric = new GenericNumber(); stringNumeric.zeroValue = ""; stringNumeric.add = function (x, y) { return x + y; };   console.log(stringNumeric.add(stringNumeric.zeroValue, "test")); Just as with interface, putting the type parameter on the class itself lets us make sure all of the properties of the class are working with the same type. As we covered in [our section on classes](classes), a class has two sides to its type: the static side and the instance side. Generic classes are only generic over their instance side rather than their static side, so when working with classes, static members can not use the class’s type parameter. ## Generic Constraints If you remember from an earlier example, you may sometimes want to write a generic function that works on a set of types where you have some knowledge about what capabilities that set of types will have. In our `loggingIdentity` example, we wanted to be able to access the `.length` property of `arg`, but the compiler could not prove that every type had a `.length` property, so it warns us that we can’t make this assumption. function loggingIdentity(arg: T): T { console.log(arg.length); return arg; } Instead of working with any and all types, we’d like to constrain this function to work with any and all types that also have the `.length` property. As long as the type has this member, we’ll allow it, but it’s required to have at least this member. To do so, we must list our requirement as a constraint on what T can be. To do so, we’ll create an interface that describes our constraint. Here, we’ll create an interface that has a single `.length` property and then we’ll use this interface and the `extends` keyword to denote our constraint: interface Lengthwise { length: number; }   function loggingIdentity(arg: T): T { console.log(arg.length); // Now we know it has a .length property, so no more error return arg; } Because the generic function is now constrained, it will no longer work over any and all types: loggingIdentity(3); Instead, we need to pass in values whose type has all the required properties: loggingIdentity({ length: 10, value: 3 }); ### Using Type Parameters in Generic Constraints You can declare a type parameter that is constrained by another type parameter. For example, here we’d like to get a property from an object given its name. We’d like to ensure that we’re not accidentally grabbing a property that does not exist on the `obj`, so we’ll place a constraint between the two types: function getProperty(obj: T, key: K) { return obj[key]; }   let x = { a: 1, b: 2, c: 3, d: 4 };   getProperty(x, "a"); getProperty(x, "m"); ### Using Class Types in Generics When creating factories in TypeScript using generics, it is necessary to refer to class types by their constructor functions. For example, function create(c: { new (): T }): T { return new c(); } A more advanced example uses the prototype property to infer and constrain relationships between the constructor function and the instance side of class types. class BeeKeeper { hasMask: boolean; }   class ZooKeeper { nametag: string; }   class Animal { numLegs: number; }   class Bee extends Animal { keeper: BeeKeeper; }   class Lion extends Animal { keeper: ZooKeeper; }   function createInstance
(c: new () => A): A { return new c(); }   createInstance(Lion).keeper.nametag; createInstance(Bee).keeper.hasMask; ##### On this page * Hello World of Generics * Working with Generic Type Variables * Generic Types * Generic Classes * Generic Constraints * Using Type Parameters in Generic Constraints * Using Class Types in Generics ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/handbook-v1/Generics.md) ❤ Contributors to this page: RC OT DR MH RC 15+ Last updated: Mar 11, 2025 # Gulp Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) # Gulp This quick start guide will teach you how to build TypeScript with [gulp](https://gulpjs.com) and then add [Browserify](https://browserify.org), [terser](https://terser.org), or [Watchify](https://github.com/substack/watchify) to the gulp pipeline. This guide also shows how to add [Babel](https://babeljs.io/) functionality using [Babelify](https://github.com/babel/babelify). We assume that you’re already using [Node.js](https://nodejs.org/) with [npm](https://www.npmjs.com/). ## Minimal project Let’s start out with a new directory. We’ll name it `proj` for now, but you can change it to whatever you want. mkdir proj cd proj To start, we’re going to structure our project in the following way: proj/ ├─ src/ └─ dist/ TypeScript files will start out in your `src` folder, run through the TypeScript compiler and end up in `dist`. Let’s scaffold this out: mkdir src mkdir dist ### Initialize the project Now we’ll turn this folder into an npm package. npm init You’ll be given a series of prompts. You can use the defaults except for your entry point. For your entry point, use `./dist/main.js`. You can always go back and change these in the `package.json` file that’s been generated for you. ### Install our dependencies Now we can use `npm install` to install packages. First install `gulp-cli` globally (if you use a Unix system, you may need to prefix the `npm install` commands in this guide with `sudo`). npm install -g gulp-cli Then install `typescript`, `gulp` and `gulp-typescript` in your project’s dev dependencies. [Gulp-typescript](https://www.npmjs.com/package/gulp-typescript) is a gulp plugin for TypeScript. npm install --save-dev typescript gulp@4.0.0 gulp-typescript ### Write a simple example Let’s write a Hello World program. In `src`, create the file `main.ts`: function hello(compiler: string) { console.log(`Hello from ${compiler}`); } hello("TypeScript"); In the project root, `proj`, create the file `tsconfig.json`: { "files": ["src/main.ts"], "compilerOptions": { "noImplicitAny": true, "target": "es5" } } ### Create a `gulpfile.js` In the project root, create the file `gulpfile.js`: var gulp = require("gulp"); var ts = require("gulp-typescript"); var tsProject = ts.createProject("tsconfig.json"); gulp.task("default", function () { return tsProject.src().pipe(tsProject()).js.pipe(gulp.dest("dist")); }); ### Test the resulting app gulp node dist/main.js The program should print “Hello from TypeScript!“. ## Add modules to the code Before we get to Browserify, let’s build our code out and add modules to the mix. This is the structure you’re more likely to use for a real app. Create a file called `src/greet.ts`: export function sayHello(name: string) { return `Hello from ${name}`; } Now change the code in `src/main.ts` to import `sayHello` from `greet.ts`: import { sayHello } from "./greet"; console.log(sayHello("TypeScript")); Finally, add `src/greet.ts` to `tsconfig.json`: { "files": ["src/main.ts", "src/greet.ts"], "compilerOptions": { "noImplicitAny": true, "target": "es5" } } Make sure that the modules work by running `gulp` and then testing in Node: gulp node dist/main.js Notice that even though we used ES2015 module syntax, TypeScript emitted CommonJS modules that Node uses. We’ll stick with CommonJS for this tutorial, but you could set `module` in the options object to change this. ## Browserify Now let’s move this project from Node to the browser. To do this, we’d like to bundle all our modules into one JavaScript file. Fortunately, that’s exactly what Browserify does. Even better, it lets us use the CommonJS module system used by Node, which is the default TypeScript emit. That means our TypeScript and Node setup will transfer to the browser basically unchanged. First, install browserify, [tsify](https://www.npmjs.com/package/tsify), and vinyl-source-stream. tsify is a Browserify plugin that, like gulp-typescript, gives access to the TypeScript compiler. vinyl-source-stream lets us adapt the file output of Browserify back into a format that gulp understands called [vinyl](https://github.com/gulpjs/vinyl). npm install --save-dev browserify tsify vinyl-source-stream ### Create a page Create a file in `src` named `index.html`: Hello World!

Loading ...

Now change `main.ts` to update the page: import { sayHello } from "./greet"; function showHello(divName: string, name: string) { const elt = document.getElementById(divName); elt.innerText = sayHello(name); } showHello("greeting", "TypeScript"); Calling `showHello` calls `sayHello` to change the paragraph’s text. Now change your gulpfile to the following: var gulp = require("gulp"); var browserify = require("browserify"); var source = require("vinyl-source-stream"); var tsify = require("tsify"); var paths = { pages: ["src/*.html"], }; gulp.task("copy-html", function () { return gulp.src(paths.pages).pipe(gulp.dest("dist")); }); gulp.task( "default", gulp.series(gulp.parallel("copy-html"), function () { return browserify({ basedir: ".", debug: true, entries: ["src/main.ts"], cache: {}, packageCache: {}, }) .plugin(tsify) .bundle() .pipe(source("bundle.js")) .pipe(gulp.dest("dist")); }) ); This adds the `copy-html` task and adds it as a dependency of `default`. That means any time `default` is run, `copy-html` has to run first. We’ve also changed `default` to call Browserify with the tsify plugin instead of gulp- typescript. Conveniently, they both allow us to pass the same options object to the TypeScript compiler. After calling `bundle` we use `source` (our alias for vinyl-source-stream) to name our output bundle `bundle.js`. Test the page by running gulp and then opening `dist/index.html` in a browser. You should see “Hello from TypeScript” on the page. Notice that we specified `debug: true` to Browserify. This causes tsify to emit source maps inside the bundled JavaScript file. Source maps let you debug your original TypeScript code in the browser instead of the bundled JavaScript. You can test that source maps are working by opening the debugger for your browser and putting a breakpoint inside `main.ts`. When you refresh the page the breakpoint should pause the page and let you debug `greet.ts`. ## Watchify, Babel, and Terser Now that we are bundling our code with Browserify and tsify, we can add various features to our build with browserify plugins. * Watchify starts gulp and keeps it running, incrementally compiling whenever you save a file. This lets you keep an edit-save-refresh cycle going in the browser. * Babel is a hugely flexible compiler that converts ES2015 and beyond into ES5 and ES3. This lets you add extensive and customized transformations that TypeScript doesn’t support. * Terser compacts your code so that it takes less time to download. ### Watchify We’ll start with Watchify to provide background compilation: npm install --save-dev watchify fancy-log Now change your gulpfile to the following: var gulp = require("gulp"); var browserify = require("browserify"); var source = require("vinyl-source-stream"); var watchify = require("watchify"); var tsify = require("tsify"); var fancy_log = require("fancy-log"); var paths = { pages: ["src/*.html"], }; var watchedBrowserify = watchify( browserify({ basedir: ".", debug: true, entries: ["src/main.ts"], cache: {}, packageCache: {}, }).plugin(tsify) ); gulp.task("copy-html", function () { return gulp.src(paths.pages).pipe(gulp.dest("dist")); }); function bundle() { return watchedBrowserify .bundle() .on("error", fancy_log) .pipe(source("bundle.js")) .pipe(gulp.dest("dist")); } gulp.task("default", gulp.series(gulp.parallel("copy-html"), bundle)); watchedBrowserify.on("update", bundle); watchedBrowserify.on("log", fancy_log); There are basically three changes here, but they require you to refactor your code a bit. 1. We wrapped our `browserify` instance in a call to `watchify`, and then held on to the result. 2. We called `watchedBrowserify.on('update', bundle);` so that Browserify will run the `bundle` function every time one of your TypeScript files changes. 3. We called `watchedBrowserify.on('log', fancy_log);` to log to the console. Together (1) and (2) mean that we have to move our call to `browserify` out of the `default` task. And we have to give the function for `default` a name since both Watchify and Gulp need to call it. Adding logging with (3) is optional but very useful for debugging your setup. Now when you run Gulp, it should start and stay running. Try changing the code for `showHello` in `main.ts` and saving it. You should see output that looks like this: proj$ gulp [10:34:20] Using gulpfile ~/src/proj/gulpfile.js [10:34:20] Starting 'copy-html'... [10:34:20] Finished 'copy-html' after 26 ms [10:34:20] Starting 'default'... [10:34:21] 2824 bytes written (0.13 seconds) [10:34:21] Finished 'default' after 1.36 s [10:35:22] 2261 bytes written (0.02 seconds) [10:35:24] 2808 bytes written (0.05 seconds) ### Terser First install Terser. Since the point of Terser is to mangle your code, we also need to install vinyl-buffer and gulp-sourcemaps to keep sourcemaps working. npm install --save-dev gulp-terser vinyl-buffer gulp-sourcemaps Now change your gulpfile to the following: var gulp = require("gulp"); var browserify = require("browserify"); var source = require("vinyl-source-stream"); var terser = require("gulp-terser"); var tsify = require("tsify"); var sourcemaps = require("gulp-sourcemaps"); var buffer = require("vinyl-buffer"); var paths = { pages: ["src/*.html"], }; gulp.task("copy-html", function () { return gulp.src(paths.pages).pipe(gulp.dest("dist")); }); gulp.task( "default", gulp.series(gulp.parallel("copy-html"), function () { return browserify({ basedir: ".", debug: true, entries: ["src/main.ts"], cache: {}, packageCache: {}, }) .plugin(tsify) .bundle() .pipe(source("bundle.js")) .pipe(buffer()) .pipe(sourcemaps.init({ loadMaps: true })) .pipe(terser()) .pipe(sourcemaps.write("./")) .pipe(gulp.dest("dist")); }) ); Notice that `terser` itself has just one call — the calls to `buffer` and `sourcemaps` exist to make sure sourcemaps keep working. These calls give us a separate sourcemap file instead of using inline sourcemaps like before. Now you can run Gulp and check that `bundle.js` does get minified into an unreadable mess: gulp cat dist/bundle.js ### Babel First install Babelify and the Babel preset for ES2015. Like Terser, Babelify mangles code, so we’ll need vinyl-buffer and gulp-sourcemaps. By default Babelify will only process files with extensions of `.js`, `.es`, `.es6` and `.jsx` so we need to add the `.ts` extension as an option to Babelify. npm install --save-dev babelify@8 babel-core babel-preset-es2015 vinyl-buffer gulp-sourcemaps Now change your gulpfile to the following: var gulp = require("gulp"); var browserify = require("browserify"); var source = require("vinyl-source-stream"); var tsify = require("tsify"); var sourcemaps = require("gulp-sourcemaps"); var buffer = require("vinyl-buffer"); var paths = { pages: ["src/*.html"], }; gulp.task("copy-html", function () { return gulp.src(paths.pages).pipe(gulp.dest("dist")); }); gulp.task( "default", gulp.series(gulp.parallel("copy-html"), function () { return browserify({ basedir: ".", debug: true, entries: ["src/main.ts"], cache: {}, packageCache: {}, }) .plugin(tsify) .transform("babelify", { presets: ["es2015"], extensions: [".ts"], }) .bundle() .pipe(source("bundle.js")) .pipe(buffer()) .pipe(sourcemaps.init({ loadMaps: true })) .pipe(sourcemaps.write("./")) .pipe(gulp.dest("dist")); }) ); We also need to have TypeScript target ES2015. Babel will then produce ES5 from the ES2015 code that TypeScript emits. Let’s modify `tsconfig.json`: { "files": ["src/main.ts"], "compilerOptions": { "noImplicitAny": true, "target": "es2015" } } Babel’s ES5 output should be very similar to TypeScript’s output for such a simple script. ##### On this page * Minimal project * Initialize the project * Install our dependencies * Write a simple example * Create a gulpfile.js * Test the resulting app * Add modules to the code * Browserify * Create a page * Watchify, Babel, and Terser * Watchify * Terser * Babel ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/tutorials/Gulp.md) ❤ Contributors to this page: BK OT DR RC MF 19+ Last updated: Mar 11, 2025 # Integrating with Build Tools Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) # Integrating with Build Tools ## Babel ### Install npm install @babel/cli @babel/core @babel/preset-typescript --save-dev ### .babelrc { "presets": ["@babel/preset-typescript"] } ### Using Command Line Interface ./node_modules/.bin/babel --out-file bundle.js src/index.ts ### package.json { "scripts": { "build": "babel --out-file bundle.js main.ts" }, } ### Execute Babel from the command line npm run build ## Browserify ### Install npm install tsify ### Using Command Line Interface browserify main.ts -p [ tsify --noImplicitAny ] > bundle.js ### Using API var browserify = require("browserify"); var tsify = require("tsify"); browserify() .add("main.ts") .plugin("tsify", { noImplicitAny: true }) .bundle() .pipe(process.stdout); More details: [smrq/tsify](https://github.com/smrq/tsify) ## Grunt ### Using `grunt-ts` (no longer maintained) #### Install npm install grunt-ts --save-dev #### Basic Gruntfile.js module.exports = function (grunt) { grunt.initConfig({ ts: { default: { src: ["**/*.ts", "!node_modules/**/*.ts"], }, }, }); grunt.loadNpmTasks("grunt-ts"); grunt.registerTask("default", ["ts"]); }; More details: [TypeStrong/grunt-ts](https://github.com/TypeStrong/grunt-ts) ### Using `grunt-browserify` combined with `tsify` #### Install npm install grunt-browserify tsify --save-dev #### Basic Gruntfile.js module.exports = function (grunt) { grunt.initConfig({ browserify: { all: { src: "src/main.ts", dest: "dist/main.js", options: { plugin: ["tsify"], }, }, }, }); grunt.loadNpmTasks("grunt-browserify"); grunt.registerTask("default", ["browserify"]); }; More details: [jmreidy/grunt-browserify](https://github.com/jmreidy/grunt- browserify), [TypeStrong/tsify](https://github.com/TypeStrong/tsify) ## Gulp ### Install npm install gulp-typescript ### Basic gulpfile.js var gulp = require("gulp"); var ts = require("gulp-typescript"); gulp.task("default", function () { var tsResult = gulp.src("src/*.ts").pipe( ts({ noImplicitAny: true, out: "output.js", }) ); return tsResult.js.pipe(gulp.dest("built/local")); }); More details: [ivogabe/gulp-typescript](https://github.com/ivogabe/gulp- typescript) ## Jspm ### Install npm install -g jspm@beta _Note: Currently TypeScript support in jspm is in 0.16beta_ More details: [TypeScriptSamples/jspm](https://github.com/Microsoft/TypeScriptSamples/tree/master/jspm) ## MSBuild Update project file to include locally installed `Microsoft.TypeScript.Default.props` (at the top) and `Microsoft.TypeScript.targets` (at the bottom) files: false true true false More details about defining MSBuild compiler options: [Setting Compiler Options in MSBuild projects](compiler-options-in-msbuild) ## NuGet * Right-Click -> Manage NuGet Packages * Search for `Microsoft.TypeScript.MSBuild` * Hit `Install` * When install is complete, rebuild! More details can be found at [Package Manager Dialog](http://docs.nuget.org/Consume/Package-Manager-Dialog) and [using nightly builds with NuGet](https://github.com/Microsoft/TypeScript/wiki/Nightly-drops#using-nuget- with-msbuild) ## Rollup ### Install npm install @rollup/plugin-typescript --save-dev Note that both `typescript` and `tslib` are peer dependencies of this plugin that need to be installed separately. ### Usage Create a `rollup.config.js` [configuration file](https://www.rollupjs.org/guide/en/#configuration-files) and import the plugin: // rollup.config.js import typescript from '@rollup/plugin-typescript'; export default { input: 'src/index.ts', output: { dir: 'output', format: 'cjs' }, plugins: [typescript()] }; ## Svelte Compiler ### Install npm install --save-dev svelte-preprocess Note that `typescript` is an optional peer dependencies of this plugin and needs to be installed separately. `tslib` is not provided either. You may also consider [`svelte-check`](https://www.npmjs.com/package/svelte- check) for CLI type checking. ### Usage Create a `svelte.config.js` configuration file and import the plugin: // svelte.config.js import preprocess from 'svelte-preprocess'; const config = { // Consult https://github.com/sveltejs/svelte-preprocess // for more information about preprocessors preprocess: preprocess() }; export default config; You can now specify that script blocks are written in TypeScript: import {} from "lodash"; // Browser: https://esm.sh/lodash@4.17.21 // TypeScript: ./node_modules/@types/lodash/index.d.ts ## I’m writing a library Choosing compilation settings as a library author is a fundamentally different process from choosing settings as an app author. When writing an app, settings are chosen that reflect the runtime environment or bundler—typically a single entity with known behavior. When writing a library, you would ideally check your code under _all possible_ library consumer compilation settings. Since this is impractical, you can instead use the strictest possible settings, since satisfying those tends to satisfy all others. { "compilerOptions": { "module": "node18", "target": "es2020", // set to the *lowest* target you support "strict": true, "verbatimModuleSyntax": true, "declaration": true, "sourceMap": true, "declarationMap": true, "rootDir": "src", "outDir": "dist" } } Let’s examine why we picked each of these settings: * **`module: "node18"`**. When a codebase is compatible with Node.js’s module system, it almost always works in bundlers as well. If you’re using a third-party emitter to emit ESM outputs, ensure that you set `"type": "module"` in your package.json so TypeScript checks your code as ESM, which uses a stricter module resolution algorithm in Node.js than CommonJS does. As an example, let’s look at what would happen if a library were to compile with `"moduleResolution": "bundler"`: export * from "./utils"; Assuming `./utils.ts` (or `./utils/index.ts`) exists, a bundler would be fine with this code, so `"moduleResolution": "bundler"` doesn’t complain. Compiled with `"module": "esnext"`, the output JavaScript for this export statement will look exactly the same as the input. If that JavaScript were published to npm, it would be usable by projects that use a bundler, but it would cause an error when run in Node.js: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '.../node_modules/dependency/utils' imported from .../node_modules/dependency/index.js Did you mean to import ./utils.js? On the other hand, if we had written: export * from "./utils.js"; This would produce output that works both in Node.js _and_ in bundlers. In short, `"moduleResolution": "bundler"` is infectious, allowing code that only works in bundlers to be produced. Likewise, `"moduleResolution": "nodenext"` is only checking that the output works in Node.js, but in most cases, module code that works in Node.js will work in other runtimes and in bundlers. * **`target: "es2020"`**. Setting this value to the _lowest_ ECMAScript version that you intend to support ensures the emitted code will not use language features introduced in a later version. Since `target` also implies a corresponding value for `lib`, this also ensures you don’t access globals that may not be available in older environments. * **`strict: true`**. Without this, you may write type-level code that ends up in your output `.d.ts` files and errors when a consumer compiles with `strict` enabled. For example, this `extends` clause: export interface Super { foo: string; } export interface Sub extends Super { foo: string | undefined; } is only an error under `strictNullChecks`. On the other hand, it’s very difficult to write code that errors only when `strict` is _disabled_ , so it’s highly recommended for libraries to compile with `strict`. * **`verbatimModuleSyntax: true`**. This setting protects against a few module-related pitfalls that can cause problems for library consumers. First, it prevents writing any import statements that could be interpreted ambiguously based on the user’s value of `esModuleInterop` or `allowSyntheticDefaultImports`. Previously, it was often suggested that libraries compile without `esModuleInterop`, since its use in libraries could force users to adopt it too. However, it’s also possible to write imports that only work _without_ `esModuleInterop`, so neither value for the setting guarantees portability for libraries. `verbatimModuleSyntax` does provide such a guarantee.1 Second, it prevents the use of `export default` in modules that will be emitted as CommonJS, which can require bundler users and Node.js ESM users to consume the module differently. See the appendix on [ESM/CJS Interop](../appendices/esm-cjs-interop#library-code-needs-special-considerations) for more details. * **`declaration: true`** emits type declaration files alongside the output JavaScript. This is needed for consumers of the library to have any type information. * **`sourceMap: true`** and **`declarationMap: true`** emit source maps for the output JavaScript and type declaration files, respectively. These are only useful if the library also ships its source (`.ts`) files. By shipping source maps and source files, consumers of the library will be able to debug the library code somewhat more easily. By shipping declaration maps and source files, consumers will be able to see the original TypeScript sources when they run Go To Definition on imports from the libraries. Both of these represent a tradeoff between developer experience and library size, so it’s up to you whether to include them. * **`rootDir: "src"`** and **`outDir: "dist"`**. Using a separate output directory is always a good idea, but it’s _necessary_ for libraries that publish their input files. Otherwise, [extension substitution](../reference#file-extension-substitution) will cause the library’s consumers to load the library’s `.ts` files instead of `.d.ts` files, causing type errors and performance problems. ### Considerations for bundling libraries If you’re using a bundler to emit your library, then all your (non- externalized) imports will be processed by the bundler with known behavior, not by your users’ unknowable environments. In this case, you can use `"module": "esnext"` and `"moduleResolution": "bundler"`, but only with two caveats: 1. TypeScript cannot model module resolution when some files are bundled and some are externalized. When bundling libraries with dependencies, it’s common to bundle the first-party library source code into a single file, but leave imports of external dependencies as real imports in the bundled output. This essentially means module resolution is split between the bundler and the end user’s environment. To model this in TypeScript, you would want to process bundled imports with `"moduleResolution": "bundler"` and externalized imports with `"moduleResolution": "nodenext"` (or with multiple options to check that everything will work in a range of end-user environments). But TypeScript cannot be configured to use two different module resolution settings in the same compilation. As a consequence, using `"moduleResolution": "bundler"` may allow imports of externalized dependencies that would work in a bundler but are unsafe in Node.js. On the other hand, using `"moduleResolution": "nodenext"` may impose overly strict requirements on bundled imports. 2. You must ensure that your declaration files get bundled as well. Recall the [first rule of declaration files](../theory#the-role-of-declaration-files): every declaration file represents exactly one JavaScript file. If you use `"moduleResolution": "bundler"` and use a bundler to emit an ESM bundle while using `tsc` to emit many individual declaration files, your declaration files may cause errors when consumed under `"module": "nodenext"`. For example, an input file like: import { Component } from "./extensionless-relative-import"; will have its import erased by the JS bundler, but produce a declaration file with an identical import statement. That import statement, however, will contain an invalid module specifier in Node.js, since it’s missing a file extension. For Node.js users, TypeScript will error on the declaration file and infect types referencing `Component` with `any`, assuming the dependency will crash at runtime. If your TypeScript bundler does not produce bundled declaration files, use `"moduleResolution": "nodenext"` to ensure that the imports preserved in your declaration files will be compatible with end-users’ TypeScript settings. Even better, consider not bundling your library. ### Notes on dual-emit solutions A single TypeScript compilation (whether emitting or just type checking) assumes that each input file will only produce one output file. Even if `tsc` isn’t emitting anything, the type checking it performs on imported names rely on knowledge about how the output file will behave at runtime, based on the module- and emit-related options set in the tsconfig.json. While third-party emitters are generally safe to use in combination with `tsc` type checking as long as `tsc` can be configured to understand what the other emitter will emit, any solution that emits two different sets of outputs with different module formats while only type checking once leaves (at least) one of the outputs unchecked. Because external dependencies may expose different APIs to CommonJS and ESM consumers, there’s no configuration you can use to guarantee in a single compilation that both outputs will be type-safe. In practice, most dependencies follow best practices and dual-emit outputs work. Running tests and [static analysis](https://npmjs.com/package/@arethetypeswrong/cli) against all output bundles before publishing significantly reduces the chance of a serious problem going unnoticed. * * * 1. `verbatimModuleSyntax` can only work when the JS emitter emits the same module kind as `tsc` would given the tsconfig.json, source file extension, and package.json `"type"`. The option works by enforcing that the `import`/`require` written is identical to the `import`/`require` emitted. Any configuration that produces both an ESM and a CJS output from the same source file is fundamentally incompatible with `verbatimModuleSyntax`, since its whole purpose is to prevent you from writing `import` anywhere that a `require` would be emitted. `verbatimModuleSyntax` can also be defeated by configuring a third-party emitter to emit a different module kind than `tsc` would—for example, by setting `"module": "esnext"` in tsconfig.json while configuring Babel to emit CommonJS.↩ ##### On this page * I’m writing an app * I’m using a bundler * I’m compiling and running the outputs in Node.js * I’m using ts-node * I’m using tsx * I’m writing ES modules for the browser, with no bundler or module compiler * I’m writing a library * Considerations for bundling libraries * Notes on dual-emit solutions ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/modules- reference/guides/Choosing%20Compiler%20Options.md) ❤ Contributors to this page: AB TM Last updated: Mar 11, 2025 # Modules - Introduction Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](../2/basic-types) * [Everyday Types](../2/everyday-types) * [Narrowing](../2/narrowing) * [More on Functions](../2/functions) * [Object Types](../2/objects) * Type Manipulation * [Creating Types from Types](../2/types-from-types) * [Generics](../2/generics) * [Keyof Type Operator](../2/keyof-types) * [Typeof Type Operator](../2/typeof-types) * [Indexed Access Types](../2/indexed-access-types) * [Conditional Types](../2/conditional-types) * [Mapped Types](../2/mapped-types) * [Template Literal Types](../2/template-literal-types) * [Classes](../2/classes) * [Modules](../2/modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](introduction) * [Theory](theory) * Guides * [Choosing Compiler Options](guides/choosing-compiler-options) * [Reference](reference) * Appendices * [ESM/CJS Interoperability](appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Modules - Introduction This document is divided into four sections: 1. The first section develops the [**theory**](theory) behind how TypeScript approaches modules. If you want to be able to write the correct module-related compiler options for any situation, reason about how to integrate TypeScript with other tools, or understand how TypeScript processes dependency packages, this is the place to start. While there are guides and reference pages on these topics, building an understanding of these fundamentals will make reading the guides easier, and give you a mental framework for dealing with real-world problems not specifically covered here. 2. The [**guides**](guides/choosing-compiler-options) show how to accomplish specific real-world tasks, starting with picking the right compilation settings for a new project. The guides are a good place to start both for beginners who want to get up and running as quickly as possible and for experts who already have a good grasp of the theory but want concrete guidance on a complicated task. 3. The [**reference**](reference) section provides a more detailed look at the syntaxes and configurations presented in previous sections. 4. The [**appendices**](appendices/esm-cjs-interop) cover complicated topics that deserve additional explanation in more detail than the theory or reference sections allow. ##### On this page ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/modules- reference/Introduction.md) ❤ Contributors to this page: AB Last updated: Mar 11, 2025 # Modules - Reference Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](../2/basic-types) * [Everyday Types](../2/everyday-types) * [Narrowing](../2/narrowing) * [More on Functions](../2/functions) * [Object Types](../2/objects) * Type Manipulation * [Creating Types from Types](../2/types-from-types) * [Generics](../2/generics) * [Keyof Type Operator](../2/keyof-types) * [Typeof Type Operator](../2/typeof-types) * [Indexed Access Types](../2/indexed-access-types) * [Conditional Types](../2/conditional-types) * [Mapped Types](../2/mapped-types) * [Template Literal Types](../2/template-literal-types) * [Classes](../2/classes) * [Modules](../2/modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](introduction) * [Theory](theory) * Guides * [Choosing Compiler Options](guides/choosing-compiler-options) * [Reference](reference) * Appendices * [ESM/CJS Interoperability](appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Modules - Reference ## Module syntax The TypeScript compiler recognizes standard [ECMAScript module syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) in TypeScript and JavaScript files and many forms of [CommonJS syntax](../type-checking-javascript-files#commonjs-modules-are-supported) in JavaScript files. There are also a few TypeScript-specific syntax extensions that can be used in TypeScript files and/or JSDoc comments. ### Importing and exporting TypeScript-specific declarations Type aliases, interfaces, enums, and namespaces can be exported from a module with an `export` modifier, like any standard JavaScript declaration: // Standard JavaScript syntax... export function f() {} // ...extended to type declarations export type SomeType = /* ... */; export interface SomeInterface { /* ... */ } They can also be referenced in named exports, even alongside references to standard JavaScript declarations: export { f, SomeType, SomeInterface }; Exported types (and other TypeScript-specific declarations) can be imported with standard ECMAScript imports: import { f, SomeType, SomeInterface } from "./module.js"; When using namespace imports or exports, exported types are available on the namespace when referenced in a type position: import * as mod from "./module.js"; mod.f(); mod.SomeType; // Property 'SomeType' does not exist on type 'typeof import("./module.js")' let x: mod.SomeType; // Ok ### Type-only imports and exports When emitting imports and exports to JavaScript, by default, TypeScript automatically elides (does not emit) imports that are only used in type positions and exports that only refer to types. Type-only imports and exports can be used to force this behavior and make the elision explicit. Import declarations written with `import type`, export declarations written with `export type { ... }`, and import or export specifiers prefixed with the `type` keyword are all guaranteed to be elided from the output JavaScript. // @Filename: main.ts import { f, type SomeInterface } from "./module.js"; import type { SomeType } from "./module.js"; class C implements SomeInterface { constructor(p: SomeType) { f(); } } export type { C }; // @Filename: main.js import { f } from "./module.js"; class C { constructor(p) { f(); } } Even values can be imported with `import type`, but since they won’t exist in the output JavaScript, they can only be used in non-emitting positions: import type { f } from "./module.js"; f(); // 'f' cannot be used as a value because it was imported using 'import type' let otherFunction: typeof f = () => {}; // Ok A type-only import declaration may not declare both a default import and named bindings, since it appears ambiguous whether `type` applies to the default import or to the entire import declaration. Instead, split the import declaration into two, or use `default` as a named binding: import type fs, { BigIntOptions } from "fs"; // ^^^^^^^^^^^^^^^^^^^^^ // Error: A type-only import can specify a default import or named bindings, but not both. import type { default as fs, BigIntOptions } from "fs"; // Ok ### `import()` types TypeScript provides a type syntax similar to JavaScript’s dynamic `import` for referencing the type of a module without writing an import declaration: // Access an exported type: type WriteFileOptions = import("fs").WriteFileOptions; // Access the type of an exported value: type WriteFileFunction = typeof import("fs").writeFile; This is especially useful in JSDoc comments in JavaScript files, where it’s not possible to import types otherwise: /** @type {import("webpack").Configuration} */ module.exports = { // ... } ### `export =` and `import = require()` When emitting CommonJS modules, TypeScript files can use a direct analog of `module.exports = ...` and `const mod = require("...")` JavaScript syntax: // @Filename: main.ts import fs = require("fs"); export = fs.readFileSync("..."); // @Filename: main.js "use strict"; const fs = require("fs"); module.exports = fs.readFileSync("..."); This syntax was used over its JavaScript counterparts since variable declarations and property assignments could not refer to TypeScript types, whereas special TypeScript syntax could: // @Filename: a.ts interface Options { /* ... */ } module.exports = Options; // Error: 'Options' only refers to a type, but is being used as a value here. export = Options; // Ok // @Filename: b.ts const Options = require("./a"); const options: Options = { /* ... */ }; // Error: 'Options' refers to a value, but is being used as a type here. // @Filename: c.ts import Options = require("./a"); const options: Options = { /* ... */ }; // Ok ### Ambient modules TypeScript supports a syntax in script (non-module) files for declaring a module that exists in the runtime but has no corresponding file. These _ambient modules_ usually represent runtime-provided modules, like `"fs"` or `"path"` in Node.js: declare module "path" { export function normalize(p: string): string; export function join(...paths: any[]): string; export var sep: string; } Once an ambient module is loaded into a TypeScript program, TypeScript will recognize imports of the declared module in other files: // 👇 Ensure the ambient module is loaded - // may be unnecessary if path.d.ts is included // by the project tsconfig.json somehow. /// import { normalize, join } from "path"; Ambient module declarations are easy to confuse with [module augmentations](../declaration-merging#module-augmentation) since they use identical syntax. This module declaration syntax becomes a module augmentation when the file is a module, meaning it has a top-level `import` or `export` statement (or is affected by [`--moduleDetection force` or `auto`](../../../tsconfig#moduleDetection)): // Not an ambient module declaration anymore! export {}; declare module "path" { export function normalize(p: string): string; export function join(...paths: any[]): string; export var sep: string; } Ambient modules may use imports inside the module declaration body to refer to other modules without turning the containing file into a module (which would make the ambient module declaration a module augmentation): declare module "m" { // Moving this outside "m" would totally change the meaning of the file! import { SomeType } from "other"; export function f(): SomeType; } A _pattern_ ambient module contains a single `*` wildcard character in its name, matching zero or more characters in import paths. This can be useful for declaring modules provided by custom loaders: declare module "*.html" { const content: string; export default content; } ## The `module` compiler option This section discusses the details of each `module` compiler option value. See the [_Module output format_](theory#the-module-output-format) theory section for more background on what the option is and how it fits into the overall compilation process. In brief, the `module` compiler option was historically only used to control the output module format of emitted JavaScript files. The more recent `node16`, `node18`, and `nodenext` values, however, describe a wide range of characteristics of Node.js’s module system, including what module formats are supported, how the module format of each file is determined, and how different module formats interoperate. ### `node16`, `node18`, `nodenext` Node.js supports both CommonJS and ECMAScript modules, with specific rules for which format each file can be and how the two formats are allowed to interoperate. `node16`, `node18`, and `nodenext` describe the full range of behavior for Node.js’s dual-format module system, and **emit files in either CommonJS or ESM format**. This is different from every other `module` option, which are runtime-agnostic and force all output files into a single format, leaving it to the user to ensure the output is valid for their runtime. > A common misconception is that `node16`—`nodenext` only emit ES modules. In > reality, these modes describe versions of Node.js that _support_ ES modules, > not just projects that _use_ ES modules. Both ESM and CommonJS emit are > supported, based on the detected module format of each file. Because they > are the only `module` options that reflect the complexities of Node.js’s > dual module system, they are the **only correct`module` options** for all > apps and libraries that are intended to run in Node.js v12 or later, whether > they use ES modules or not. The fixed-version `node16` and `node18` modes represent the module system behavior stabilized in their respective Node.js versions, while the `nodenext` mode changes with the latest stable versions of Node.js. The following table summarizes the current differences between the three modes: | `target` | `moduleResolution` | import assertions | import attributes | JSON imports | require(esm) ---|---|---|---|---|---|--- node16 | `es2022` | `node16` | ❌ | ❌ | no restrictions | ❌ node18 | `es2022` | `node16` | ✅ | ✅ | needs `type "json"` | ❌ nodenext | `esnext` | `nodenext` | ❌ | ✅ | needs `type "json"` | ✅ #### Module format detection * `.mts`/`.mjs`/`.d.mts` files are always ES modules. * `.cts`/`.cjs`/`.d.cts` files are always CommonJS modules. * `.ts`/`.tsx`/`.js`/`.jsx`/`.d.ts` files are ES modules if the nearest ancestor package.json file contains `"type": "module"`, otherwise CommonJS modules. The detected module format of input `.ts`/`.tsx`/`.mts`/`.cts` files determines the module format of the emitted JavaScript files. So, for example, a project consisting entirely of `.ts` files will emit all CommonJS modules by default under `--module nodenext`, and can be made to emit all ES modules by adding `"type": "module"` to the project package.json. #### Interoperability rules * **When an ES module references a CommonJS module:** * The `module.exports` of the CommonJS module is available as a default import to the ES module. * Properties (other than `default`) of the CommonJS module’s `module.exports` may or may not be available as named imports to the ES module. Node.js attempts to make them available via [static analysis](https://github.com/nodejs/cjs-module-lexer). TypeScript cannot know from a declaration file whether that static analysis will succeed, and optimistically assumes it will. This limits TypeScript’s ability to catch named imports that may crash at runtime. See [#54018](https://github.com/microsoft/TypeScript/issues/54018) for more details. * **When a CommonJS module references an ES module:** * In `node16` and `node18`, `require` cannot reference an ES module. For TypeScript, this includes `import` statements in files that are detected to be CommonJS modules, since those `import` statements will be transformed to `require` calls in the emitted JavaScript. * In `nodenext`, to reflect the behavior of Node.js v22.12.0 and later, `require` can reference an ES module. In Node.js, an error is thrown if the ES module, or any of its imported modules, uses top-level `await`. TypeScript does not attempt to detect this case and will not emit a compile-time error. The result of the `require` call is the module’s Module Namespace Object, i.e., the same as the result of an `await import()` of the same module (but without the need to `await` anything). * A dynamic `import()` call can always be used to import an ES module. It returns a Promise of the module’s Module Namespace Object (what you’d get from `import * as ns from "./module.js"` from another ES module). #### Emit The emit format of each file is determined by the detected module format of each file. ESM emit is similar to `--module esnext`, but has a special transformation for `import x = require("...")`, which is not allowed in `--module esnext`: // @Filename: main.ts import x = require("mod"); // @Filename: main.js import { createRequire as _createRequire } from "module"; const __require = _createRequire(import.meta.url); const x = __require("mod"); CommonJS emit is similar to `--module commonjs`, but dynamic `import()` calls are not transformed. Emit here is shown with `esModuleInterop` enabled: // @Filename: main.ts import fs from "fs"; // transformed const dynamic = import("mod"); // not transformed // @Filename: main.js "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); // transformed const dynamic = import("mod"); // not transformed #### Implied and enforced options * `--module nodenext` implies and enforces `--moduleResolution nodenext`. * `--module node18` or `node16` implies and enforces `--moduleResolution node16`. * `--module nodenext` implies `--target esnext`. * `--module node18` or `node16` implies `--target es2022`. * `--module nodenext` or `node18` or `node16` implies `--esModuleInterop`. #### Summary * `node16`, `node18`, and `nodenext` are the only correct `module` options for all apps and libraries that are intended to run in Node.js v12 or later, whether they use ES modules or not. * `node16`, `node18`, and `nodenext` emit files in either CommonJS or ESM format, based on the detected module format of each file. * Node.js’s interoperability rules between ESM and CJS are reflected in type checking. * ESM emit transforms `import x = require("...")` to a `require` call constructed from a `createRequire` import. * CommonJS emit leaves dynamic `import()` calls untransformed, so CommonJS modules can asynchronously import ES modules. ### `preserve` In `--module preserve` ([added](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-4.html#support-for-require-calls-in---moduleresolution- bundler-and---module-preserve) in TypeScript 5.4), ECMAScript imports and exports written in input files are preserved in the output, and CommonJS-style `import x = require("...")` and `export = ...` statements are emitted as CommonJS `require` and `module.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). 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 setting `noEmit`? TypeScript’s type checking and module > resolution behavior are affected by the module format that it _would_ emit. > Setting `module` 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. See `--moduleResolution bundler` for more discussion. #### Examples import x, { y, z } from "mod"; import mod = require("mod"); const dynamic = import("mod"); export const e1 = 0; export default "default export"; import x, { y, z } from "mod"; const mod = require("mod"); const dynamic = import("mod"); export const e1 = 0; export default "default export"; #### Implied and enforced options * `--module preserve` implies `--moduleResolution bundler`. * `--module preserve` implies `--esModuleInterop`. > The option `--esModuleInterop` is enabled by default in `--module preserve` > only for its [type checking](appendices/esm-cjs- > interop#allowsyntheticdefaultimports-and-esmoduleinterop) behavior. Since > imports never transform into require calls in `--module preserve`, > `--esModuleInterop` does not affect the emitted JavaScript. ### `es2015`, `es2020`, `es2022`, `esnext` #### Summary * Use `esnext` with `--moduleResolution bundler` for bundlers, Bun, and tsx. * Do not use for Node.js. Use `node16`, `node18`, or `nodenext` with `"type": "module"` in package.json to emit ES modules for Node.js. * `import mod = require("mod")` is not allowed in non-declaration files. * `es2020` adds support for `import.meta` properties. * `es2022` adds support for top-level `await`. * `esnext` is a moving target that may include support for Stage 3 proposals to ECMAScript modules. * Emitted files are ES modules, but dependencies may be any format. #### Examples // @Filename: main.ts import x, { y, z } from "mod"; import * as mod from "mod"; const dynamic = import("mod"); console.log(x, y, z, mod, dynamic); export const e1 = 0; export default "default export"; // @Filename: main.js import x, { y, z } from "mod"; import * as mod from "mod"; const dynamic = import("mod"); console.log(x, y, z, mod, dynamic); export const e1 = 0; export default "default export"; ### `commonjs` #### Summary * You probably shouldn’t use this. Use `node16`, `node18`, or `nodenext` to emit CommonJS modules for Node.js. * Emitted files are CommonJS modules, but dependencies may be any format. * Dynamic `import()` is transformed to a Promise of a `require()` call. * `esModuleInterop` affects the output code for default and namespace imports. #### Examples > Output is shown with `esModuleInterop: false`. // @Filename: main.ts import x, { y, z } from "mod"; import * as mod from "mod"; const dynamic = import("mod"); console.log(x, y, z, mod, dynamic); export const e1 = 0; export default "default export"; // @Filename: main.js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.e1 = void 0; const mod_1 = require("mod"); const mod = require("mod"); const dynamic = Promise.resolve().then(() => require("mod")); console.log(mod_1.default, mod_1.y, mod_1.z, mod); exports.e1 = 0; exports.default = "default export"; // @Filename: main.ts import mod = require("mod"); console.log(mod); export = { p1: true, p2: false }; // @Filename: main.js "use strict"; const mod = require("mod"); console.log(mod); module.exports = { p1: true, p2: false }; ### `system` #### Summary * Designed for use with the [SystemJS module loader](https://github.com/systemjs/systemjs). #### Examples // @Filename: main.ts import x, { y, z } from "mod"; import * as mod from "mod"; const dynamic = import("mod"); console.log(x, y, z, mod, dynamic); export const e1 = 0; export default "default export"; // @Filename: main.js System.register(["mod"], function (exports_1, context_1) { "use strict"; var mod_1, mod, dynamic, e1; var __moduleName = context_1 && context_1.id; return { setters: [ function (mod_1_1) { mod_1 = mod_1_1; mod = mod_1_1; } ], execute: function () { dynamic = context_1.import("mod"); console.log(mod_1.default, mod_1.y, mod_1.z, mod, dynamic); exports_1("e1", e1 = 0); exports_1("default", "default export"); } }; }); ### `amd` #### Summary * Designed for AMD loaders like RequireJS. * You probably shouldn’t use this. Use a bundler instead. * Emitted files are AMD modules, but dependencies may be any format. * Supports `outFile`. #### Examples // @Filename: main.ts import x, { y, z } from "mod"; import * as mod from "mod"; const dynamic = import("mod"); console.log(x, y, z, mod, dynamic); export const e1 = 0; export default "default export"; // @Filename: main.js define(["require", "exports", "mod", "mod"], function (require, exports, mod_1, mod) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.e1 = void 0; const dynamic = new Promise((resolve_1, reject_1) => { require(["mod"], resolve_1, reject_1); }); console.log(mod_1.default, mod_1.y, mod_1.z, mod, dynamic); exports.e1 = 0; exports.default = "default export"; }); ### `umd` #### Summary * Designed for AMD or CommonJS loaders. * Does not expose a global variable like most other UMD wrappers. * You probably shouldn’t use this. Use a bundler instead. * Emitted files are UMD modules, but dependencies may be any format. #### Examples // @Filename: main.ts import x, { y, z } from "mod"; import * as mod from "mod"; const dynamic = import("mod"); console.log(x, y, z, mod, dynamic); export const e1 = 0; export default "default export"; // @Filename: main.js (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", "mod", "mod"], factory); } })(function (require, exports) { "use strict"; var __syncRequire = typeof module === "object" && typeof module.exports === "object"; Object.defineProperty(exports, "__esModule", { value: true }); exports.e1 = void 0; const mod_1 = require("mod"); const mod = require("mod"); const dynamic = __syncRequire ? Promise.resolve().then(() => require("mod")) : new Promise((resolve_1, reject_1) => { require(["mod"], resolve_1, reject_1); }); console.log(mod_1.default, mod_1.y, mod_1.z, mod, dynamic); exports.e1 = 0; exports.default = "default export"; }); ## The `moduleResolution` compiler option This section describes module resolution features and processes shared by multiple `moduleResolution` modes, then specifies the details of each mode. See the [_Module resolution_](theory#module-resolution) theory section for more background on what the option is and how it fits into the overall compilation process. In brief, `moduleResolution` controls how TypeScript resolves _module specifiers_ (string literals in `import`/`export`/`require` statements) to files on disk, and should be set to match the module resolver used by the target runtime or bundler. ### Common features and processes #### File extension substitution TypeScript always wants to resolve internally to a file that can provide type information, while ensuring that the runtime or bundler can use the same path to resolve to a file that provides a JavaScript implementation. For any module specifier that would, according to the `moduleResolution` algorithm specified, trigger a lookup of a JavaScript file in the runtime or bundler, TypeScript will first try to find a TypeScript implementation file or type declaration file with the same name and analagous file extension. Runtime lookup | TypeScript lookup #1 | TypeScript lookup #2 | TypeScript lookup #3 | TypeScript lookup #4 | TypeScript lookup #5 ---|---|---|---|---|--- `/mod.js` | `/mod.ts` | `/mod.tsx` | `/mod.d.ts` | `/mod.js` | `./mod.jsx` `/mod.mjs` | `/mod.mts` | `/mod.d.mts` | `/mod.mjs` | | `/mod.cjs` | `/mod.cts` | `/mod.d.cts` | `/mod.cjs` | | Note that this behavior is independent of the actual module specifier written in the import. This means that TypeScript can resolve to a `.ts` or `.d.ts` file even if the module specifier explicitly uses a `.js` file extension: import x from "./mod.js"; // Runtime lookup: "./mod.js" // TypeScript lookup #1: "./mod.ts" // TypeScript lookup #2: "./mod.d.ts" // TypeScript lookup #3: "./mod.js" See [_TypeScript imitates the host’s module resolution, but with types_](theory#typescript-imitates-the-hosts-module-resolution-but-with-types) for an explanation of why TypeScript’s module resolution works this way. #### Relative file path resolution All of TypeScript’s `moduleResolution` algorithms support referencing a module by a relative path that includes a file extension (which will be substituted according to the rules above): // @Filename: a.ts export {}; // @Filename: b.ts import {} from "./a.js"; // ✅ Works in every `moduleResolution` #### Extensionless relative paths In some cases, the runtime or bundler allows omitting a `.js` file extension from a relative path. TypeScript supports this behavior where the `moduleResolution` setting and the context indicate that the runtime or bundler supports it: // @Filename: a.ts export {}; // @Filename: b.ts import {} from "./a"; If TypeScript determines that the runtime will perform a lookup for `./a.js` given the module specifier `"./a"`, then `./a.js` will undergo extension substitution, and resolve to the file `a.ts` in this example. Extensionless relative paths are not supported in `import` paths in Node.js, and are not always supported in file paths specified in package.json files. TypeScript currently never supports omitting a `.mjs`/`.mts` or `.cjs`/`.cts` file extension, even though some runtimes and bundlers do. #### Directory modules (index file resolution) In some cases, a directory, rather than a file, can be referenced as a module. In the simplest and most common case, this involves the runtime or bundler looking for an `index.js` file in a directory. TypeScript supports this behavior where the `moduleResolution` setting and the context indicate that the runtime or bundler supports it: // @Filename: dir/index.ts export {}; // @Filename: b.ts import {} from "./dir"; If TypeScript determines that the runtime will perform a lookup for `./dir/index.js` given the module specifier `"./dir"`, then `./dir/index.js` will undergo extension substitution, and resolve to the file `dir/index.ts` in this example. Directory modules may also contain a package.json file, where resolution of the `"main"` and `"types"` fields are supported, and take precedence over `index.js` lookups. The `"typesVersions"` field is also supported in directory modules. Note that directory modules are not the same as `node_modules` packages and only support a subset of the features available to packages, and are not supported at all in some contexts. Node.js considers them a [legacy feature](https://nodejs.org/dist/latest-v20.x/docs/api/modules.html#folders- as-modules). #### `paths` ##### Overview TypeScript offers a way to override the compiler’s module resolution for bare specifiers with the `paths` compiler option. While the feature was originally designed to be used with the AMD module loader (a means of running modules in the browser before ESM existed or bundlers were widely used), it still has uses today when a runtime or bundler supports module resolution features that TypeScript does not model. For example, when running Node.js with `--experimental-network-imports`, you can manually specify a local type definition file for a specific `https://` import: { "compilerOptions": { "module": "nodenext", "paths": { "https://esm.sh/lodash@4.17.21": ["./node_modules/@types/lodash/index.d.ts"] } } } // Typed by ./node_modules/@types/lodash/index.d.ts due to `paths` entry import { add } from "https://esm.sh/lodash@4.17.21"; It’s also common for apps built with bundlers to define convenience path aliases in their bundler configuration, and then inform TypeScript of those aliases with `paths`: { "compilerOptions": { "module": "esnext", "moduleResolution": "bundler", "paths": { "@app/*": ["./src/*"] } } } ##### `paths` does not affect emit The `paths` option does _not_ change the import path in the code emitted by TypeScript. Consequently, it’s very easy to create path aliases that appear to work in TypeScript but will crash at runtime: { "compilerOptions": { "module": "nodenext", "paths": { "node-has-no-idea-what-this-is": ["./oops.ts"] } } } // TypeScript: ✅ // Node.js: 💥 import {} from "node-has-no-idea-what-this-is"; While it’s ok for bundled apps to set up `paths`, it’s very important that published libraries do _not_ , since the emitted JavaScript will not work for consumers of the library without those users setting up the same aliases for both TypeScript and their bundler. Both libraries and apps can consider package.json `"imports"` as a standard replacement for convenience `paths` aliases. ##### `paths` should not point to monorepo packages or node_modules packages While module specifiers that match `paths` aliases are bare specifiers, once the alias is resolved, module resolution proceeds on the resolved path as a relative path. Consequently, resolution features that happen for `node_modules` package lookups, including package.json `"exports"` field support, do not take effect when a `paths` alias is matched. This can lead to surprising behavior if `paths` is used to point to a `node_modules` package: { "compilerOptions": { "paths": { "pkg": ["./node_modules/pkg/dist/index.d.ts"], "pkg/*": ["./node_modules/pkg/*"] } } } While this configuration may simulate some of the behavior of package resolution, it overrides any `main`, `types`, `exports`, and `typesVersions` the package’s `package.json` file defines, and imports from the package may fail at runtime. The same caveat applies to packages referencing each other in a monorepo. Instead of using `paths` to make TypeScript artificially resolve `"@my- scope/lib"` to a sibling package, it’s best to use workspaces via [npm](https://docs.npmjs.com/cli/v7/using-npm/workspaces), [yarn](https://classic.yarnpkg.com/en/docs/workspaces/), or [pnpm](https://pnpm.io/workspaces) to symlink your packages into `node_modules`, so both TypeScript and the runtime or bundler perform real `node_modules` package lookups. This is especially important if the monorepo packages will be published to npm—the packages will reference each other via `node_modules` package lookups once installed by users, and using workspaces allows you to test that behavior during local development. ##### Relationship to `baseUrl` When `baseUrl` is provided, the values in each `paths` array are resolved relative to the `baseUrl`. Otherwise, they are resolved relative to the `tsconfig.json` file that defines them. ##### Wildcard substitutions `paths` patterns can contain a single `*` wildcard, which matches any string. The `*` token can then be used in the file path values to substitute the matched string: { "compilerOptions": { "paths": { "@app/*": ["./src/*"] } } } When resolving an import of `"@app/components/Button"`, TypeScript will match on `@app/*`, binding `*` to `components/Button`, and then attempt to resolve the path `./src/components/Button` relative to the `tsconfig.json` path. The remainder of this lookup will follow the same rules as any other relative path lookup according to the `moduleResolution` setting. When multiple patterns match a module specifier, the pattern with the longest matching prefix before any `*` token is used: { "compilerOptions": { "paths": { "*": ["./src/foo/one.ts"], "foo/*": ["./src/foo/two.ts"], "foo/bar": ["./src/foo/three.ts"] } } } When resolving an import of `"foo/bar"`, all three `paths` patterns match, but the last is used because `"foo/bar"` is longer than `"foo/"` and `""`. ##### Fallbacks Multiple file paths can be provided for a path mapping. If resolution fails for one path, the next one in the array will be attempted until resolution succeeds or the end of the array is reached. { "compilerOptions": { "paths": { "*": ["./vendor/*", "./types/*"] } } } #### `baseUrl` > `baseUrl` was designed for use with AMD module loaders. If you aren’t using > an AMD module loader, you probably shouldn’t use `baseUrl`. Since TypeScript > 4.1, `baseUrl` is no longer required to use `paths` and should not be used > just to set the directory `paths` values are resolved from. The `baseUrl` compiler option can be combined with any `moduleResolution` mode and specifies a directory that bare specifiers (module specifiers that don’t begin with `./`, `../`, or `/`) are resolved from. `baseUrl` has a higher precedence than `node_modules` package lookups in `moduleResolution` modes that support them. When performing a `baseUrl` lookup, resolution proceeds with the same rules as other relative path resolutions. For example, in a `moduleResolution` mode that supports extensionless relative paths a module specifier `"some-file"` may resolve to `/src/some-file.ts` if `baseUrl` is set to `/src`. Resolution of relative module specifiers are never affected by the `baseUrl` option. #### `node_modules` package lookups Node.js treats module specifiers that aren’t relative paths, absolute paths, or URLs as references to packages that it looks up in `node_modules` subdirectories. Bundlers conveniently adopted this behavior to allow their users to use the same dependency management system, and often even the same dependencies, as they would in Node.js. All of TypeScript’s `moduleResolution` options except `classic` support `node_modules` lookups. (`classic` supports lookups in `node_modules/@types` when other means of resolution fail, but never looks for packages in `node_modules` directly.) Every `node_modules` package lookup has the following structure (beginning after higher precedence bare specifier rules, like `paths`, `baseUrl`, self-name imports, and package.json `"imports"` lookups have been exhausted): 1. For each ancestor directory of the importing file, if a `node_modules` directory exists within it: 1. If a directory with the same name as the package exists within `node_modules`: 1. Attempt to resolve types from the package directory. 2. If a result is found, return it and stop the search. 2. If a directory with the same name as the package exists within `node_modules/@types`: 1. Attempt to resolve types from the `@types` package directory. 2. If a result is found, return it and stop the search. 2. Repeat the previous search through all `node_modules` directories, but this time, allow JavaScript files as a result, and do not search in `@types` directories. All `moduleResolution` modes (except `classic`) follow this pattern, while the details of how they resolve from a package directory, once located, differ, and are explained in the following sections. #### package.json `"exports"` When `moduleResolution` is set to `node16`, `nodenext`, or `bundler`, and `resolvePackageJsonExports` is not disabled, TypeScript follows Node.js’s [package.json `"exports"` spec](https://nodejs.org/api/packages.html#packages_package_entry_points) when resolving from a package directory triggered by a bare specifier `node_modules` package lookup. TypeScript’s implementation for resolving a module specifier through `"exports"` to a file path follows Node.js exactly. Once a file path is resolved, however, TypeScript will still try multiple file extensions in order to prioritize finding types. When resolving through [conditional `"exports"`](https://nodejs.org/api/packages.html#conditional-exports), TypeScript always matches the `"types"` and `"default"` conditions if present. Additionally, TypeScript will match a versioned types condition in the form `"types@{selector}"` (where `{selector}` is a `"typesVersions"`-compatible version selector) according to the same version-matching rules implemented in `"typesVersions"`. Other non-configurable conditions are dependent on the `moduleResolution` mode and specified in the following sections. Additional conditions can be configured to match with the `customConditions` compiler option. Note that the presence of `"exports"` prevents any subpaths not explicitly listed or matched by a pattern in `"exports"` from being resolved. ##### Example: subpaths, conditions, and extension substitution Scenario: `"pkg/subpath"` is requested with conditions `["types", "node", "require"]` (determined by `moduleResolution` setting and the context that triggered the module resolution request) in a package directory with the following package.json: { "name": "pkg", "exports": { ".": { "import": "./index.mjs", "require": "./index.cjs" }, "./subpath": { "import": "./subpath/index.mjs", "require": "./subpath/index.cjs" } } } Resolution process within the package directory: 1. Does `"exports"` exist? **Yes.** 2. Does `"exports"` have a `"./subpath"` entry? **Yes.** 3. The value at `exports["./subpath"]` is an object—it must be specifying conditions. 4. Does the first condition `"import"` match this request? **No.** 5. Does the second condition `"require"` match this request? **Yes.** 6. Does the path `"./subpath/index.cjs"` have a recognized TypeScript file extension? **No, so use extension substitution.** 7. Via extension substitution, try the following paths, returning the first one that exists, or `undefined` otherwise: 1. `./subpath/index.cts` 2. `./subpath/index.d.cts` 3. `./subpath/index.cjs` If `./subpath/index.cts` or `./subpath.d.cts` exists, resolution is complete. Otherwise, resolution searches `node_modules/@types/pkg` and other `node_modules` directories in an attempt to resolve types, according to the `node_modules` package lookups rules. If no types are found, a second pass through all `node_modules` resolves to `./subpath/index.cjs` (assuming it exists), which counts as a successful resolution, but one that does not provide types, leading to `any`-typed imports and a `noImplicitAny` error if enabled. ##### Example: explicit `"types"` condition Scenario: `"pkg/subpath"` is requested with conditions `["types", "node", "import"]` (determined by `moduleResolution` setting and the context that triggered the module resolution request) in a package directory with the following package.json: { "name": "pkg", "exports": { "./subpath": { "import": { "types": "./types/subpath/index.d.mts", "default": "./es/subpath/index.mjs" }, "require": { "types": "./types/subpath/index.d.cts", "default": "./cjs/subpath/index.cjs" } } } } Resolution process within the package directory: 1. Does `"exports"` exist? **Yes.** 2. Does `"exports"` have a `"./subpath"` entry? **Yes.** 3. The value at `exports["./subpath"]` is an object—it must be specifying conditions. 4. Does the first condition `"import"` match this request? **Yes.** 5. The value at `exports["./subpath"].import` is an object—it must be specifying conditions. 6. Does the first condition `"types"` match this request? **Yes.** 7. Does the path `"./types/subpath/index.d.mts"` have a recognized TypeScript file extension? **Yes, so don’t use extension substitution.** 8. Return the path `"./types/subpath/index.d.mts"` if the file exists, `undefined` otherwise. ##### Example: versioned `"types"` condition Scenario: using TypeScript 4.7.5, `"pkg/subpath"` is requested with conditions `["types", "node", "import"]` (determined by `moduleResolution` setting and the context that triggered the module resolution request) in a package directory with the following package.json: { "name": "pkg", "exports": { "./subpath": { "types@>=5.2": "./ts5.2/subpath/index.d.ts", "types@>=4.6": "./ts4.6/subpath/index.d.ts", "types": "./tsold/subpath/index.d.ts", "default": "./dist/subpath/index.js" } } } Resolution process within the package directory: 1. Does `"exports"` exist? **Yes.** 2. Does `"exports"` have a `"./subpath"` entry? **Yes.** 3. The value at `exports["./subpath"]` is an object—it must be specifying conditions. 4. Does the first condition `"types@>=5.2"` match this request? **No, 4.7.5 is not greater than or equal to 5.2.** 5. Does the second condition `"types@>=4.6"` match this request? **Yes, 4.7.5 is greater than or equal to 4.6.** 6. Does the path `"./ts4.6/subpath/index.d.ts"` have a recognized TypeScript file extension? **Yes, so don’t use extension substitution.** 7. Return the path `"./ts4.6/subpath/index.d.ts"` if the file exists, `undefined` otherwise. ##### Example: subpath patterns Scenario: `"pkg/wildcard.js"` is requested with conditions `["types", "node", "import"]` (determined by `moduleResolution` setting and the context that triggered the module resolution request) in a package directory with the following package.json: { "name": "pkg", "type": "module", "exports": { "./*.js": { "types": "./types/*.d.ts", "default": "./dist/*.js" } } } Resolution process within the package directory: 1. Does `"exports"` exist? **Yes.** 2. Does `"exports"` have a `"./wildcard.js"` entry? **No.** 3. Does any key with a `*` in it match `"./wildcard.js"`? **Yes,`"./*.js"` matches and sets `wildcard` to be the substitution.** 4. The value at `exports["./*.js"]` is an object—it must be specifying conditions. 5. Does the first condition `"types"` match this request? **Yes.** 6. In `./types/*.d.ts`, replace `*` with the substitution `wildcard`. **`./types/wildcard.d.ts`** 7. Does the path `"./types/wildcard.d.ts"` have a recognized TypeScript file extension? **Yes, so don’t use extension substitution.** 8. Return the path `"./types/wildcard.d.ts"` if the file exists, `undefined` otherwise. ##### Example: `"exports"` block other subpaths Scenario: `"pkg/dist/index.js"` is requested in a package directory with the following package.json: { "name": "pkg", "main": "./dist/index.js", "exports": "./dist/index.js" } Resolution process within the package directory: 1. Does `"exports"` exist? **Yes.** 2. The value at `exports` is a string—it must be a file path for the package root (`"."`). 3. Is the request `"pkg/dist/index.js"` for the package root? **No, it has a subpath`dist/index.js`.** 4. Resolution fails; return `undefined`. Without `"exports"`, the request could have succeeded, but the presence of `"exports"` prevents resolving any subpaths that cannot be matched through `"exports"`. #### package.json `"typesVersions"` A `node_modules` package or directory module may specify a `"typesVersions"` field in its package.json to redirect TypeScript’s resolution process according to the TypeScript compiler version, and for `node_modules` packages, according to the subpath being resolved. This allows package authors to include new TypeScript syntax in one set of type definitions while providing another set for backward compatibility with older TypeScript versions (through a tool like [downlevel-dts](https://github.com/sandersn/downlevel-dts)). `"typesVersions"` is supported in all `moduleResolution` modes; however, the field is not read in situations when package.json `"exports"` are read. ##### Example: redirect all requests to a subdirectory Scenario: a module imports `"pkg"` using TypeScript 5.2, where `node_modules/pkg/package.json` is: { "name": "pkg", "version": "1.0.0", "types": "./index.d.ts", "typesVersions": { ">=3.1": { "*": ["ts3.1/*"] } } } Resolution process: 1. (Depending on compiler options) Does `"exports"` exist? **No.** 2. Does `"typesVersions"` exist? **Yes.** 3. Is the TypeScript version `>=3.1`? **Yes. Remember the mapping`"*": ["ts3.1/*"]`.** 4. Are we resolving a subpath after the package name? **No, just the root`"pkg"`.** 5. Does `"types"` exist? **Yes.** 6. Does any key in `"typesVersions"` match `./index.d.ts`? **Yes,`"*"` matches and sets `index.d.ts` to be the substitution.** 7. In `ts3.1/*`, replace `*` with the substitution `./index.d.ts`: **`ts3.1/index.d.ts`**. 8. Does the path `./ts3.1/index.d.ts` have a recognized TypeScript file extension? **Yes, so don’t use extension substitution.** 9. Return the path `./ts3.1/index.d.ts` if the file exists, `undefined` otherwise. ##### Example: redirect requests for a specific file Scenario: a module imports `"pkg"` using TypeScript 3.9, where `node_modules/pkg/package.json` is: { "name": "pkg", "version": "1.0.0", "types": "./index.d.ts", "typesVersions": { "<4.0": { "index.d.ts": ["index.v3.d.ts"] } } } Resolution process: 1. (Depending on compiler options) Does `"exports"` exist? **No.** 2. Does `"typesVersions"` exist? **Yes.** 3. Is the TypeScript version `<4.0`? **Yes. Remember the mapping`"index.d.ts": ["index.v3.d.ts"]`.** 4. Are we resolving a subpath after the package name? **No, just the root`"pkg"`.** 5. Does `"types"` exist? **Yes.** 6. Does any key in `"typesVersions"` match `./index.d.ts`? **Yes,`"index.d.ts"` matches.** 7. Does the path `./index.v3.d.ts` have a recognized TypeScript file extension? **Yes, so don’t use extension substitution.** 8. Return the path `./index.v3.d.ts` if the file exists, `undefined` otherwise. #### package.json `"main"` and `"types"` If a directory’s package.json `"exports"` field is not read (either due to compiler options, or because it is not present, or because the directory is being resolved as a directory module instead of a `node_modules` package) and the module specifier does not have a subpath after the package name or package.json-containing directory, TypeScript will attempt to resolve from these package.json fields, in order, in an attempt to find the main module for the package or directory: * `"types"` * `"typings"` (legacy) * `"main"` The declaration file found at `"types"` is assumed to be an accurate representation of the implementation file found at `"main"`. If `"types"` and `"typings"` are not present or cannot be resolved, TypeScript will read the `"main"` field and perform extension substitution to find a declaration file. When publishing a typed package to npm, it’s recommended to include a `"types"` field even if extension substitution or package.json `"exports"` make it unnecessary, because npm shows a TS icon on the package registry listing only if the package.json contains a `"types"` field. #### Package-relative file paths If neither package.json `"exports"` nor package.json `"typesVersions"` apply, subpaths of a bare package specifier resolve relative to the package directory, according to applicable relative path resolution rules. In modes that respect [package.json `"exports"`], this behavior is blocked by the mere presence of the `"exports"` field in the package’s package.json, even if the import fails to resolve through `"exports"`, as demonstrated in an example above. On the other hand, if the import fails to resolve through `"typesVersions"`, a package-relative file path resolution is attempted as a fallback. When package-relative paths are supported, they resolve under the same rules as any other relative path considering the `moduleResolution` mode and context. For example, in `--moduleResolution nodenext`, directory modules and extensionless paths are only supported in `require` calls, not in `import`s: // @Filename: module.mts import "pkg/dist/foo"; // ❌ import, needs `.js` extension import "pkg/dist/foo.js"; // ✅ import foo = require("pkg/dist/foo"); // ✅ require, no extension needed #### package.json `"imports"` and self-name imports When `moduleResolution` is set to `node16`, `nodenext`, or `bundler`, and `resolvePackageJsonImports` is not disabled, TypeScript will attempt to resolve import paths beginning with `#` through the `"imports"` field of the nearest ancestor package.json of the importing file. Similarly, when package.json `"exports"` lookups are enabled, TypeScript will attempt to resolve import paths beginning with the current package name—that is, the value in the `"name"` field of the nearest ancestor package.json of the importing file—through the `"exports"` field of that package.json. Both of these features allow files in a package to import other files in the same package, replacing a relative import path. TypeScript follows Node.js’s resolution algorithm for [`"imports"`](https://nodejs.org/api/packages.html#subpath-imports) and [self references](https://nodejs.org/api/packages.html#self-referencing-a-package- using-its-name) exactly up until a file path is resolved. At that point, TypeScript’s resolution algorithm forks based on whether the package.json containing the `"imports"` or `"exports"` being resolved belongs to a `node_modules` dependency or the local project being compiled (i.e., its directory contains the tsconfig.json file for the project that contains the importing file): * If the package.json is in `node_modules`, TypeScript will apply extension substitution to the file path if it doesn’t already have a recognized TypeScript file extension, and check for the existence of the resulting file paths. * If the package.json is part of the local project, an additional remapping step is performed in order to find the _input_ TypeScript implementation file that will eventually produce the output JavaScript or declaration file path that was resolved from `"imports"`. Without this step, any compilation that resolves an `"imports"` path would be referencing output files from the _previous compilation_ instead of other input files that are intended to be included in the current compilation. This remapping uses the `outDir`/`declarationDir` and `rootDir` from the tsconfig.json, so using `"imports"` usually requires an explicit `rootDir` to be set. This variation allows package authors to write `"imports"` and `"exports"` fields that reference only the compilation outputs that will be published to npm, while still allowing local development to use the original TypeScript source files. ##### Example: local project with conditions Scenario: `"/src/main.mts"` imports `"#utils"` with conditions `["types", "node", "import"]` (determined by `moduleResolution` setting and the context that triggered the module resolution request) in a project directory with a tsconfig.json and package.json: // tsconfig.json { "compilerOptions": { "moduleResolution": "node16", "resolvePackageJsonImports": true, "rootDir": "./src", "outDir": "./dist" } } // package.json { "name": "pkg", "imports": { "#utils": { "import": "./dist/utils.d.mts", "require": "./dist/utils.d.cts" } } } Resolution process: 1. Import path starts with `#`, try to resolve through `"imports"`. 2. Does `"imports"` exist in the nearest ancestor package.json? **Yes.** 3. Does `"#utils"` exist in the `"imports"` object? **Yes.** 4. The value at `imports["#utils"]` is an object—it must be specifying conditions. 5. Does the first condition `"import"` match this request? **Yes.** 6. Should we attempt to map the output path to an input path? **Yes, because:** * Is the package.json in `node_modules`? **No, it’s in the local project.** * Is the tsconfig.json within the package.json directory? **Yes.** 7. In `./dist/utils.d.mts`, replace the `outDir` prefix with `rootDir`. **`./src/utils.d.mts`** 8. Replace the output extension `.d.mts` with the corresponding input extension `.mts`. **`./src/utils.mts`** 9. Return the path `"./src/utils.mts"` if the file exists. 10. Otherwise, return the path `"./dist/utils.d.mts"` if the file exists. ##### Example: `node_modules` dependency with subpath pattern Scenario: `"/node_modules/pkg/main.mts"` imports `"#internal/utils"` with conditions `["types", "node", "import"]` (determined by `moduleResolution` setting and the context that triggered the module resolution request) with the package.json: // /node_modules/pkg/package.json { "name": "pkg", "imports": { "#internal/*": { "import": "./dist/internal/*.mjs", "require": "./dist/internal/*.cjs" } } } Resolution process: 1. Import path starts with `#`, try to resolve through `"imports"`. 2. Does `"imports"` exist in the nearest ancestor package.json? **Yes.** 3. Does `"#internal/utils"` exist in the `"imports"` object? **No, check for pattern matches.** 4. Does any key with a `*` match `"#internal/utils"`? **Yes,`"#internal/*"` matches and sets `utils` to be the substitution.** 5. The value at `imports["#internal/*"]` is an object—it must be specifying conditions. 6. Does the first condition `"import"` match this request? **Yes.** 7. Should we attempt to map the output path to an input path? **No, because the package.json is in`node_modules`.** 8. In `./dist/internal/*.mjs`, replace `*` with the substitution `utils`. **`./dist/internal/utils.mjs`** 9. Does the path `./dist/internal/utils.mjs` have a recognized TypeScript file extension? **No, try extension substitution.** 10. Via extension substitution, try the following paths, returning the first one that exists, or `undefined` otherwise: 1. `./dist/internal/utils.mts` 2. `./dist/internal/utils.d.mts` 3. `./dist/internal/utils.mjs` ### `node16`, `nodenext` These modes reflect the module resolution behavior of Node.js v12 and later. (`node16` and `nodenext` are currently identical, but if Node.js makes significant changes to its module system in the future, `node16` will be frozen while `nodenext` will be updated to reflect the new behavior.) In Node.js, the resolution algorithm for ECMAScript imports is significantly different from the algorithm for CommonJS `require` calls. For each module specifier being resolved, the syntax and the module format of the importing file are first used to determine whether the module specifier will be in an `import` or `require` in the emitted JavaScript. That information is then passed into the module resolver to determine which resolution algorithm to use (and whether to use the `"import"` or `"require"` condition for package.json `"exports"` or `"imports"`). > TypeScript files that are determined to be in CommonJS format may still use > `import` and `export` syntax by default, but the emitted JavaScript will use > `require` and `module.exports` instead. This means that it’s common to see > `import` statements that are resolved using the `require` algorithm. If this > causes confusion, the `verbatimModuleSyntax` compiler option can be enabled, > which prohibits the use of `import` statements that would be emitted as > `require` calls. Note that dynamic `import()` calls are always resolved using the `import` algorithm, according to Node.js’s behavior. However, `import()` types are resolved according to the format of the importing file (for backward compatibility with existing CommonJS-format type declarations): // @Filename: module.mts import x from "./mod.js"; // `import` algorithm due to file format (emitted as-written) import("./mod.js"); // `import` algorithm due to syntax (emitted as-written) type Mod = typeof import("./mod.js"); // `import` algorithm due to file format import mod = require("./mod"); // `require` algorithm due to syntax (emitted as `require`) // @Filename: commonjs.cts import x from "./mod"; // `require` algorithm due to file format (emitted as `require`) import("./mod.js"); // `import` algorithm due to syntax (emitted as-written) type Mod = typeof import("./mod"); // `require` algorithm due to file format import mod = require("./mod"); // `require` algorithm due to syntax (emitted as `require`) #### Implied and enforced options * `--moduleResolution node16` and `nodenext` must be paired with `--module node16`, `node18`, or `nodenext`. #### Supported features Features are listed in order of precedence. | `import` | `require` ---|---|--- `paths` | ✅ | ✅ `baseUrl` | ✅ | ✅ `node_modules` package lookups | ✅ | ✅ package.json `"exports"` | ✅ matches `types`, `node`, `import` | ✅ matches `types`, `node`, `require` package.json `"imports"` and self-name imports | ✅ matches `types`, `node`, `import` | ✅ matches `types`, `node`, `require` package.json `"typesVersions"` | ✅ | ✅ Package-relative paths | ✅ when `exports` not present | ✅ when `exports` not present Full relative paths | ✅ | ✅ Extensionless relative paths | ❌ | ✅ Directory modules | ❌ | ✅ ### `bundler` `--moduleResolution bundler` attempts to model the module resolution behavior common to most JavaScript bundlers. In short, this means supporting all the behaviors traditionally associated with Node.js’s CommonJS `require` resolution algorithm like `node_modules` lookups, directory modules, and extensionless paths, while also supporting newer Node.js resolution features like package.json `"exports"` and package.json `"imports"`. It’s instructive to think about the similarities and differences between `--moduleResolution bundler` and `--moduleResolution nodenext`, particularly in how they decide what conditions to use when resolving package.json `"exports"` or `"imports"`. Consider an import statement in a `.ts` file: // index.ts import { foo } from "pkg"; Recall that in `--module nodenext --moduleResolution nodenext`, the `--module` setting first determines whether the import will be emitted to the `.js` file as an `import` or `require` call, then passes that information to TypeScript’s module resolver, which decides whether to match `"import"` or `"require"` conditions in `"pkg"`’s package.json `"exports"` accordingly. Let’s assume that there’s no package.json in scope of this file. The file extension is `.ts`, so the output file extension will be `.js`, which Node.js will interpret as CommonJS, so TypeScript will emit this `import` as a `require` call. So, the module resolver will use the `require` condition as it resolves `"exports"` from `"pkg"`. The same process happens in `--moduleResolution bundler`, but the rules for deciding whether to emit an `import` or `require` call for this import statement will be different, since `--moduleResolution bundler` necessitates using `--module esnext` or `--module preserve`. In both of those modes, ESM `import` declarations always emit as ESM `import` declarations, so TypeScript’s module resolver will receive that information and use the `"import"` condition as it resolves `"exports"` from `"pkg"`. This explanation may be somewhat unintuitive, since `--moduleResolution bundler` is usually used in combination with `--noEmit`—bundlers typically process raw `.ts` files and perform module resolution on untransformed `import`s or `require`s. However, for consistency, TypeScript still uses the hypothetical emit decided by `module` to inform module resolution and type checking. This makes `--module preserve` the best choice whenever a runtime or bundler is operating on raw `.ts` files, since it implies no transformation. Under `--module preserve --moduleResolution bundler`, you can write imports and requires in the same file that will resolve with the `import` and `require` conditions, respectively: // index.ts import pkg1 from "pkg"; // Resolved with "import" condition import pkg2 = require("pkg"); // Resolved with "require" condition #### Implied and enforced options * `--moduleResolution bundler` must be paired with `--module esnext` or `--module preserve`. * `--moduleResolution bundler` implies `--allowSyntheticDefaultImports`. #### Supported features * `paths` ✅ * `baseUrl` ✅ * `node_modules` package lookups ✅ * package.json `"exports"` ✅ matches `types`, `import`/`require` depending on syntax * package.json `"imports"` and self-name imports ✅ matches `types`, `import`/`require` depending on syntax * package.json `"typesVersions"` ✅ * Package-relative paths ✅ when `exports` not present * Full relative paths ✅ * Extensionless relative paths ✅ * Directory modules ✅ ### `node10` (formerly known as `node`) `--moduleResolution node` was renamed to `node10` (keeping `node` as an alias for backward compatibility) in TypeScript 5.0. It reflects the CommonJS module resolution algorithm as it existed in Node.js versions earlier than v12. It should no longer be used. #### Supported features * `paths` ✅ * `baseUrl` ✅ * `node_modules` package lookups ✅ * package.json `"exports"` ❌ * package.json `"imports"` and self-name imports ❌ * package.json `"typesVersions"` ✅ * Package-relative paths ✅ * Full relative paths ✅ * Extensionless relative paths ✅ * Directory modules ✅ ### `classic` Do not use `classic`. ##### On this page * Module syntax * Importing and exporting TypeScript-specific declarations * Type-only imports and exports * import() types * export = and import = require() * Ambient modules * The module compiler option * node16, node18, nodenext * preserve * es2015, es2020, es2022, esnext * commonjs * system * amd * umd * The moduleResolution compiler option * Common features and processes * node16, nodenext * bundler * node10 (formerly known as node) * classic ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/modules-reference/Reference.md) ❤ Contributors to this page: AB SF SF Z HCDC Last updated: Mar 11, 2025 # Modules - Theory Was this page helpful? * Get Started * [TS for the New Programmer](../typescript-from-scratch) * [TypeScript for JS Programmers](../typescript-in-5-minutes) * [TS for Java/C# Programmers](../typescript-in-5-minutes-oop) * [TS for Functional Programmers](../typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](../typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](../intro) * [The Basics](../2/basic-types) * [Everyday Types](../2/everyday-types) * [Narrowing](../2/narrowing) * [More on Functions](../2/functions) * [Object Types](../2/objects) * Type Manipulation * [Creating Types from Types](../2/types-from-types) * [Generics](../2/generics) * [Keyof Type Operator](../2/keyof-types) * [Typeof Type Operator](../2/typeof-types) * [Indexed Access Types](../2/indexed-access-types) * [Conditional Types](../2/conditional-types) * [Mapped Types](../2/mapped-types) * [Template Literal Types](../2/template-literal-types) * [Classes](../2/classes) * [Modules](../2/modules) * Reference * [Utility Types](../utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](../decorators) * [Declaration Merging](../declaration-merging) * [Enums](../enums) * [Iterators and Generators](../iterators-and-generators) * [JSX](../jsx) * [Mixins](../mixins) * [Namespaces](../namespaces) * [Namespaces and Modules](../namespaces-and-modules) * [Symbols](../symbols) * [Triple-Slash Directives](../triple-slash-directives) * [Type Compatibility](../type-compatibility) * [Type Inference](../type-inference) * [Variable Declaration](../variable-declarations) * Modules Reference * [Introduction](introduction) * [Theory](theory) * Guides * [Choosing Compiler Options](guides/choosing-compiler-options) * [Reference](reference) * Appendices * [ESM/CJS Interoperability](appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](../asp-net-core) * [Gulp](../gulp) * [DOM Manipulation](../dom-manipulation) * [Migrating from JavaScript](../migrating-from-javascript) * [Using Babel with TypeScript](../babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](../declaration-files/introduction) * [Declaration Reference](../declaration-files/by-example) * [Library Structures](../declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](../declaration-files/templates/module-d-ts) * [Module: Plugin](../declaration-files/templates/module-plugin-d-ts) * [Module: Class](../declaration-files/templates/module-class-d-ts) * [Module: Function](../declaration-files/templates/module-function-d-ts) * [Global .d.ts](../declaration-files/templates/global-d-ts) * [Global: Modifying Module](../declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](../declaration-files/do-s-and-don-ts) * [Deep Dive](../declaration-files/deep-dive) * [Publishing](../declaration-files/publishing) * [Consumption](../declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](../intro-to-js-ts) * [Type Checking JavaScript Files](../type-checking-javascript-files) * [JSDoc Reference](../jsdoc-supported-types) * [Creating .d.ts Files from .js files](../declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](../tsconfig-json) * [Compiler Options in MSBuild](../compiler-options-in-msbuild) * [TSConfig Reference](../../../tsconfig/index) * [tsc CLI Options](../compiler-options) * [Project References](../project-references) * [Integrating with Build Tools](../integrating-with-build-tools) * [Configuring Watch](../configuring-watch) * [Nightly Builds](../nightly-builds) # Modules - Theory ## Scripts and modules in JavaScript In the early days of JavaScript, when the language only ran in browsers, there were no modules, but it was still possible to split the JavaScript for a web page into multiple files by using multiple `script` tags in HTML: This approach had some downsides, especially as web pages grew larger and more complex. In particular, all scripts loaded onto the same page share the same scope—appropriately called the “global scope”—meaning the scripts had to be very careful not to overwrite each others’ variables and functions. Any system that solves this problem by giving files their own scope while still providing a way to make bits of code available to other files can be called a “module system.” (It may sound obvious to say that each file in a module system is called a “module,” but the term is often used to contrast with _script_ files, which run outside a module system, in a global scope.) > There are [many module systems](https://github.com/myshov/history-of- > javascript/tree/master/4_evolution_of_js_modularity), and TypeScript > [supports emitting several](../../../tsconfig/index#module), but this > documentation will focus on the two most important systems today: ECMAScript > modules (ESM) and CommonJS (CJS). > > ECMAScript Modules (ESM) is the module system built into the language, > supported in modern browsers and in Node.js since v12. It uses dedicated > `import` and `export` syntax: > > > // a.js > export default "Hello from a.js"; > > > // b.js > import a from "./a.js"; > console.log(a); // 'Hello from a.js' > > CommonJS (CJS) is the module system that originally shipped in Node.js, > before ESM was part of the language specification. It’s still supported in > Node.js alongside ESM. It uses plain JavaScript objects and functions named > `exports` and `require`: > > > // a.js > exports.message = "Hello from a.js"; > > > // b.js > const a = require("./a"); > console.log(a.message); // 'Hello from a.js' Accordingly, when TypeScript detects that a file is a CommonJS or ECMAScript module, it starts by assuming that file will have its own scope. Beyond that, though, the compiler’s job gets a little more complicated. ## TypeScript’s job concerning modules The TypeScript compiler’s chief goal is to prevent certain kinds of runtime errors by catching them at compile time. With or without modules involved, the compiler needs to know about the code’s intended runtime environment—what globals are available, for example. When modules are involved, there are several additional questions the compiler needs to answer in order to do its job. Let’s use a few lines of input code as an example to think about all the information needed to analyze it: import sayHello from "greetings"; sayHello("world"); To check this file, the compiler needs to know the type of `sayHello` (is it a function that can accept one string argument?), which opens quite a few additional questions: 1. Will the module system load this TypeScript file directly, or will it load a JavaScript file that I (or another compiler) generate from this TypeScript file? 2. What _kind_ of module does the module system expect to find, given the file name it will load and its location on disk? 3. If output JavaScript is being emitted, how will the module syntax present in this file be transformed in the output code? 4. Where will the module system look to find the module specified by `"greetings"`? Will the lookup succeed? 5. What kind of module is the file resolved by that lookup? 6. Does the module system allow the kind of module detected in (2) to reference the kind of module detected in (5) with the syntax decided in (3)? 7. Once the `"greetings"` module has been analyzed, what piece of that module is bound to `sayHello`? Notice that all of these questions depend on characteristics of the _host_ —the system that ultimately consumes the output JavaScript (or raw TypeScript, as the case may be) to direct its module loading behavior, typically either a runtime (like Node.js) or bundler (like Webpack). The ECMAScript specification defines how ESM imports and exports link up with each other, but it doesn’t specify how the file lookup in (4), known as _module resolution_ , happens, and it doesn’t say anything about other module systems like CommonJS. So runtimes and bundlers, especially those that want to support both ESM and CJS, have a lot of freedom to design their own rules. Consequently, the way TypeScript should answer the questions above can vary dramatically depending on where the code is intended to run. There’s no single right answer, so the compiler must be told the rules through configuration options. The other key idea to keep in mind is that TypeScript almost always thinks about these questions in terms of its _output_ JavaScript files, not its _input_ TypeScript (or JavaScript!) files. Today, some runtimes and bundlers support loading TypeScript files directly, and in those cases, it doesn’t make sense to think about separate input and output files. Most of this document discusses cases where TypeScript files are compiled to JavaScript files, which in turn are loaded by the runtime module system. Examining these cases is essential for building an understanding of the compiler’s options and behavior—it’s easier to start there and simplify when thinking about esbuild, Bun, and other TypeScript-first runtimes and bundlers. So for now, we can summarize TypeScript’s job when it comes to modules in terms of output files: Understand the **rules of the host** enough 1. to compile files into a valid **output module format** , 2. to ensure that imports in those **outputs** will **resolve successfully** , and 3. to know what **type** to assign to **imported names**. ## Who is the host? Before we move on, it’s worth making sure we’re on the same page about the term _host_ , because it will come up frequently. We defined it before as “the system that ultimately consumes the output code to direct its module loading behavior.” In other words, it’s the system outside of TypeScript that TypeScript’s module analysis tries to model: * When the output code (whether produced by `tsc` or a third-party transpiler) is run directly in a runtime like Node.js, the runtime is the host. * When there is no “output code” because a runtime consumes TypeScript files directly, the runtime is still the host. * When a bundler consumes TypeScript inputs or outputs and produces a bundle, the bundler is the host, because it looked at the original set of imports/requires, looked up what files they referenced, and produced a new file or set of files where the original imports and requires are erased or transformed beyond recognition. (That bundle itself might comprise modules, and the runtime that runs it will be its host, but TypeScript doesn’t know about anything that happens post-bundler.) * If another transpiler, optimizer, or formatter runs on TypeScript’s outputs, it’s _not_ a host that TypeScript cares about, as long as it leaves the imports and exports it sees alone. * When loading modules in a web browser, the behaviors TypeScript needs to model are actually split between the web server and the module system running in the browser. The browser’s JavaScript engine (or a script-based module-loading framework like RequireJS) controls what module formats are accepted, while the web server decides what file to send when one module triggers a request to load another. * The TypeScript compiler itself is not a host, because it does not provide any behavior related to modules beyond trying to model other hosts. ## The module output format In any project, the first question about modules we need to answer is what kinds of modules the host expects, so TypeScript can set its output format for each file to match. Sometimes, the host only _supports_ one kind of module—ESM in the browser, or CJS in Node.js v11 and earlier, for example. Node.js v12 and later accepts both CJS and ES modules, but uses file extensions and `package.json` files to determine what format each file should be, and throws an error if the file’s contents don’t match the expected format. The `module` compiler option provides this information to the compiler. Its primary purpose is to control the module format of any JavaScript that gets emitted during compilation, but it also serves to inform the compiler about how the module kind of each file should be detected, how different module kinds are allowed to import each other, and whether features like `import.meta` and top-level `await` are available. So, even if a TypeScript project is using `noEmit`, choosing the right setting for `module` still matters. As we established earlier, the compiler needs an accurate understanding of the module system so it can type check (and provide IntelliSense for) imports. See [_Choosing compiler options_](guides/choosing- compiler-options) for guidance on choosing the right `module` setting for your project. The available `module` settings are * [**`node16`**](reference#node16-node18-nodenext): Reflects the module system of Node.js v16+, which supports ES modules and CJS modules side-by-side with particular interoperability and detection rules. * [**`node18`**](reference#node16-node18-nodenext): Reflects the module system of Node.js v18+, which adds support for import attributes. * [**`nodenext`**](reference#node16-node18-nodenext): A moving target reflecting the latest Node.js versions as Node.js’s module system evolves. As of TypeScript 5.8, `nodenext` supports `require` of ECMAScript modules. * [**`es2015`**](reference#es2015-es2020-es2022-esnext): Reflects the ES2015 language specification for JavaScript modules (the version that first introduced `import` and `export` to the language). * [**`es2020`**](reference#es2015-es2020-es2022-esnext): Adds support for `import.meta` and `export * as ns from "mod"` to `es2015`. * [**`es2022`**](reference#es2015-es2020-es2022-esnext): Adds support for top-level `await` to `es2020`. * [**`esnext`**](reference#es2015-es2020-es2022-esnext): Currently identical to `es2022`, but will be a moving target reflecting the latest ECMAScript specifications, as well as module-related Stage 3+ proposals that are expected to be included in upcoming specification versions. * **[`commonjs`](reference#commonjs), [`system`](reference#system), [`amd`](reference#amd), and [`umd`](reference#umd)**: Each emits everything in the module system named, and assumes everything can be successfully imported into that module system. These are no longer recommended for new projects and will not be covered in detail by this documentation. > Node.js’s rules for module format detection and interoperability make it > incorrect to specify `module` as `esnext` or `commonjs` for projects that > run in Node.js, even if all files emitted by `tsc` are ESM or CJS, > respectively. The only correct `module` settings for projects that intend to > run in Node.js are `node16` and `nodenext`. While the emitted JavaScript for > an all-ESM Node.js project might look identical between compilations using > `esnext` and `nodenext`, the type checking can differ. See the [reference > section on `nodenext`](reference#node16-node18-nodenext) for more details. ### Module format detection Node.js understands both ES modules and CJS modules, but the format of each file is determined by its file extension and the `type` field of the first `package.json` file found in a search of the file’s directory and all ancestor directories: * `.mjs` and `.cjs` files are always interpreted as ES modules and CJS modules, respectively. * `.js` files are interpreted as ES modules if the nearest `package.json` file contains a `type` field with the value `"module"`. If there is no `package.json` file, or if the `type` field is missing or has any other value, `.js` files are interpreted as CJS modules. If a file is determined to be an ES module by these rules, Node.js will not inject the CommonJS `module` and `require` objects into the file’s scope during evaluation, so a file that tries to use them will cause a crash. Conversely, if a file is determined to be a CJS module, `import` and `export` declarations in the file will cause a syntax error crash. When the `module` compiler option is set to `node16`, `node18`, or `nodenext`, TypeScript applies this same algorithm to the project’s _input_ files to determine the module kind of each corresponding _output_ file. Let’s look at how module formats are detected in an example project that uses `--module nodenext`: Input file name | Contents | Output file name | Module kind | Reason ---|---|---|---|--- `/package.json` | `{}` | | | `/main.mts` | | `/main.mjs` | ESM | File extension `/utils.cts` | | `/utils.cjs` | CJS | File extension `/example.ts` | | `/example.js` | CJS | No `"type": "module"` in `package.json` `/node_modules/pkg/package.json` | `{ "type": "module" }` | | | `/node_modules/pkg/index.d.ts` | | | ESM | `"type": "module"` in `package.json` `/node_modules/pkg/index.d.cts` | | | CJS | File extension When the input file extension is `.mts` or `.cts`, TypeScript knows to treat that file as an ES module or CJS module, respectively, because Node.js will treat the output `.mjs` file as an ES module or the output `.cjs` file as a CJS module. When the input file extension is `.ts`, TypeScript has to consult the nearest `package.json` file to determine the module format, because this is what Node.js will do when it encounters the output `.js` file. (Notice that the same rules apply to the `.d.cts` and `.d.ts` declaration files in the `pkg` dependency: though they will not produce an output file as part of this compilation, the presence of a `.d.ts` file _implies_ the existence of a corresponding `.js` file—perhaps created when the author of the `pkg` library ran `tsc` on an input `.ts` file of their own—which Node.js must interpret as an ES module, due to its `.js` extension and the presence of the `"type": "module"` field in `/node_modules/pkg/package.json`. Declaration files are covered in more detail in a later section.) The detected module format of input files is used by TypeScript to ensure it emits the output syntax that Node.js expects in each output file. If TypeScript were to emit `/example.js` with `import` and `export` statements in it, Node.js would crash when parsing the file. If TypeScript were to emit `/main.mjs` with `require` calls, Node.js would crash during evaluation. Beyond emit, the module format is also used to determine rules for type checking and module resolution, which we’ll discuss in the following sections. As of TypeScript 5.6, other `--module` modes (like `esnext` and `commonjs`) also respect format-specific file extensions (`.mts` and `.cts`) as a file- level override for the emit format. For example, a file named `main.mts` will emit ESM syntax into `main.mjs` even if `--module` is set to `commonjs`. It’s worth mentioning again that TypeScript’s behavior in `--module node16`, `--module node18`, and `--module nodenext` is entirely motivated by Node.js’s behavior. Since TypeScript’s goal is to catch potential runtime errors at compile time, it needs a very accurate model of what will happen at runtime. This fairly complex set of rules for module kind detection is _necessary_ for checking code that will run in Node.js, but may be overly strict or just incorrect if applied to non-Node.js hosts. ### Input module syntax It’s important to note that the _input_ module syntax seen in input source files is somewhat decoupled from the output module syntax emitted to JS files. That is, a file with an ESM import: import { sayHello } from "greetings"; sayHello("world"); might be emitted in ESM format exactly as-is, or might be emitted as CommonJS: Object.defineProperty(exports, "__esModule", { value: true }); const greetings_1 = require("greetings"); (0, greetings_1.sayHello)("world"); depending on the `module` compiler option (and any applicable module format detection rules, if the `module` option supports more than one kind of module). In general, this means that looking at the contents of an input file isn’t enough to determine whether it’s an ES module or a CJS module. > Today, most TypeScript files are authored using ESM syntax (`import` and > `export` statements) regardless of the output format. This is largely a > legacy of the long road ESM has taken to widespread support. ECMAScript > modules were standardized in 2015, were supported in most browsers by 2017, > and landed in Node.js v12 in 2019. During much of this window, it was clear > that ESM was the future of JavaScript modules, but very few runtimes could > consume it. Tools like Babel made it possible for JavaScript to be authored > in ESM and downleveled to another module format that could be used in > Node.js or browsers. TypeScript followed suit, adding support for ES module > syntax and softly discouraging the use of the original CommonJS-inspired > `import fs = require("fs")` syntax in [the 1.5 > release](https://devblogs.microsoft.com/typescript/announcing- > typescript-1-5/). > > The upside of this “author ESM, output anything” strategy was that > TypeScript could use standard JavaScript syntax, making the authoring > experience familiar to newcomers, and (theoretically) making it easy for > projects to start targeting ESM outputs in the future. There are three > significant downsides, which became fully apparent only after ESM and CJS > modules were allowed to coexist and interoperate in Node.js: > > 1. Early assumptions about how ESM/CJS interoperability would work in > Node.js turned out to be wrong, and today, interoperability rules differ > between Node.js and bundlers. Consequently, the configuration space for > modules in TypeScript is large. > 2. When the syntax in input files all looks like ESM, it’s easy for an > author or code reviewer to lose track of what kind of module a file is at > runtime. And because of Node.js’s interoperability rules, what kind of > module each file is became very important. > 3. When input files are written in ESM, the syntax in type declaration > outputs (`.d.ts` files) looks like ESM too. But because the corresponding > JavaScript files could have been emitted in any module format, TypeScript > can’t tell what kind of module a file is just by looking at the contents of > its type declarations. And again, because of the nature of ESM/CJS > interoperability, TypeScript _has_ to know what kind of module everything is > in order to provide correct types and prevent imports that will crash. > > > In TypeScript 5.0, a new compiler option called `verbatimModuleSyntax` was > introduced to help TypeScript authors know exactly how their `import` and > `export` statements will be emitted. When enabled, the flag requires imports > and exports in input files to be written in the form that will undergo the > least amount of transformation before emit. So if a file will be emitted as > ESM, imports and exports must be written in ESM syntax; if a file will be > emitted as CJS, it must be written in the CommonJS-inspired TypeScript > syntax (`import fs = require("fs")` and `export = {}`). This setting is > particularly recommended for Node.js projects that use mostly ESM, but have > a select few CJS files. It is not recommended for projects that currently > target CJS, but may want to target ESM in the future. ### ESM and CJS interoperability Can an ES module `import` a CommonJS module? If so, does a default import link to `exports` or `exports.default`? Can a CommonJS module `require` an ES module? CommonJS isn’t part of the ECMAScript specification, so runtimes, bundlers, and transpilers have been free to make up their own answers to these questions since ESM was standardized in 2015, and as such no standard set of interoperability rules exist. Today, most runtimes and bundlers broadly fall into one of three categories: 1. **ESM-only.** Some runtimes, like browser engines, only support what’s actually a part of the language: ECMAScript Modules. 2. **Bundler-like.** Before any major JavaScript engine could run ES modules, Babel allowed developers to write them by transpiling them to CommonJS. The way these ESM-transpiled-to-CJS files interacted with hand-written-CJS files implied a set of permissive interoperability rules that have become the de facto standard for bundlers and transpilers. 3. **Node.js.** Until Node.js v22.12.0, CommonJS modules could not load ES modules synchronously (with `require`); they could only load them asynchronously with dynamic `import()` calls. ES modules can default-import CJS modules, which always binds to `exports`. (This means that a default import of a Babel-like CJS output with `__esModule` behaves differently between Node.js and some bundlers.) TypeScript needs to know which of these rule sets to assume in order to provide correct types on (particularly `default`) imports and to error on imports that will crash at runtime. When the `module` compiler option is set to `node16`, `node18`, or `nodenext`, Node.js’s version-specific rules are enforced.1 All other `module` settings, combined with the [`esModuleInterop`](reference#esModuleInterop) option, result in bundler-like interop in TypeScript. (While using `--module esnext` does prevent you from _writing_ CommonJS modules, it does not prevent you from _importing_ them as dependencies. There’s currently no TypeScript setting that can guard against an ES module importing a CommonJS module, as would be appropriate for direct- to-browser code.) ### Module specifiers are not transformed by default While the `module` compiler option can transform imports and exports in input files to different module formats in output files, the module _specifier_ (the string `from` which you `import`, or pass to `require`) is emitted as-written. For example, an input like: import { add } from "./math.mjs"; add(1, 2); might be emitted as either: import { add } from "./math.mjs"; add(1, 2); or: const math_1 = require("./math.mjs"); math_1.add(1, 2); depending on the `module` compiler option, but the module specifier will be `"./math.mjs"` either way. By default, module specifiers must be written in a way that works for the code’s target runtime or bundler, and it’s TypeScript’s job to understand those _output_ -relative specifiers. The process of finding the file referenced by a module specifier is called _module resolution_. > TypeScript 5.7 introduced the [`--rewriteRelativeImportExtensions` > option](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-5-7.html#path-rewriting-for-relative-paths), which > transforms relative module specifiers with `.ts`, `.tsx`, `.mts`, or `.cts` > extensions to their JavaScript equivalents in output files. This option is > useful for creating TypeScript files that can be run directly in Node.js > during development _and_ still be compiled to JavaScript outputs for > distribution or production use. > > This documentation was written before the introduction of > `--rewriteRelativeImportExtensions`, and the mental model it presents is > built around modeling the behavior of the host module system operating on > its input files, whether that’s a bundler operating on TypeScript files or a > runtime operating on `.js` outputs. With > `--rewriteRelativeImportExtensions`, the way to apply that mental model is > to apply it _twice_ : once to the runtime or bundler processing the > TypeScript input files directly, and once again to the runtime or bundler > processing the transformed outputs. Most of this documentation assumes that > _only_ the input files or _only_ the output files will be loaded, but the > principles it presents can be extended to the case where both are loaded. ## Module resolution Let’s return to our first example and review what we’ve learned about it so far: import sayHello from "greetings"; sayHello("world"); So far, we’ve discussed how the host’s module system and TypeScript’s `module` compiler option might impact this code. We know that the input syntax looks like ESM, but the output format depends on the `module` compiler option, potentially the file extension, and `package.json` `"type"` field. We also know that what `sayHello` gets bound to, and even whether the import is even allowed, may vary depending on the module kinds of this file and the target file. But we haven’t yet discussed how to _find_ the target file. ### Module resolution is host-defined While the ECMAScript specification defines how to parse and interpret `import` and `export` statements, it leaves module resolution up to the host. If you’re creating a hot new JavaScript runtime, you’re free to create a module resolution scheme like: import monkey from "🐒"; // Looks for './eats/bananas.js' import cow from "🐄"; // Looks for './eats/grass.js' import lion from "🦁"; // Looks for './eats/you.js' and still claim to implement “standards-compliant ESM.” Needless to say, TypeScript would have no idea what types to assign to `monkey`, `cow`, and `lion` without built-in knowledge of this runtime’s module resolution algorithm. Just as `module` informs the compiler about the host’s expected module format, `moduleResolution`, along with a few customization options, specify the algorithm the host uses to resolve module specifiers to files. This also clarifies why TypeScript doesn’t modify import specifiers during emit: the relationship between an import specifier and a file on disk (if one even exists) is host-defined, and TypeScript is not a host. The available `moduleResolution` options are: * [**`classic`**](reference#classic): TypeScript’s oldest module resolution mode, this is unfortunately the default when `module` is set to anything other than `commonjs`, `node16`, or `nodenext`. It was probably made to provide best-effort resolution for a wide range of [RequireJS](https://requirejs.org/docs/api.html#packages) configurations. It should not be used for new projects (or even old projects that don’t use RequireJS or another AMD module loader), and is scheduled for deprecation in TypeScript 6.0. * [**`node10`**](reference#node10-formerly-known-as-node): Formerly known as `node`, this is the unfortunate default when `module` is set to `commonjs`. It’s a pretty good model of Node.js versions older than v12, and sometimes it’s a passable approximation of how most bundlers do module resolution. It supports looking up packages from `node_modules`, loading directory `index.js` files, and omitting `.js` extensions in relative module specifiers. Because Node.js v12 introduced different module resolution rules for ES modules, though, it’s a very bad model of modern versions of Node.js. It should not be used for new projects. * [**`node16`**](reference#node16-nodenext-1): This is the counterpart of `--module node16` and `--module node18` and is set by default with that `module` setting. Node.js v12 and later support both ESM and CJS, each of which uses its own module resolution algorithm. In Node.js, module specifiers in import statements and dynamic `import()` calls are not allowed to omit file extensions or `/index.js` suffixes, while module specifiers in `require` calls are. This module resolution mode understands and enforces this restriction where necessary, as determined by the module format detection rules instated by `--module node16`/`node18`. (For `node16` and `nodenext`, `module` and `moduleResolution` go hand-in-hand: setting one to `node16` or `nodenext` while setting the other to something else is an error.) * [**`nodenext`**](reference#node16-nodenext-1): Currently identical to `node16`, this is the counterpart of `--module nodenext` and is set by default with that `module` setting. It’s intended to be a forward-looking mode that will support new Node.js module resolution features as they’re added. * [**`bundler`**](reference#bundler): Node.js v12 introduced some new module resolution features for importing npm packages—the `"exports"` and `"imports"` fields of `package.json`—and many bundlers adopted those features without also adopting the stricter rules for ESM imports. This module resolution mode provides a base algorithm for code targeting a bundler. It supports `package.json` `"exports"` and `"imports"` by default, but can be configured to ignore them. It requires setting `module` to `esnext`. ### TypeScript imitates the host’s module resolution, but with types Remember the three components of TypeScript’s job concerning modules? 1. Compile files into a valid **output module format** 2. Ensure that imports in those **outputs** will **resolve successfully** 3. Know what **type** to assign to **imported names**. Module resolution is needed to accomplish last two. But when we spend most of our time working in input files, it can be easy to forget about (2)—that a key component of module resolution is validating that the imports or `require` calls in the output files, containing the same module specifiers as the input files, will actually work at runtime. Let’s look at a new example with multiple files: // @Filename: math.ts export function add(a: number, b: number) { return a + b; } // @Filename: main.ts import { add } from "./math"; add(1, 2); When we see the import from `"./math"`, it might be tempting to think, “This is how one TypeScript file refers to another. The compiler follows this (extensionless) path in order to assign a type to `add`.” This isn’t entirely wrong, but the reality is deeper. The resolution of `"./math"` (and subsequently, the type of `add`) need to reflect the reality of what happens at runtime to the _output_ files. A more robust way to think about this process would look like this: This model makes it clear that for TypeScript, module resolution is mostly a matter of accurately modeling the host’s module resolution algorithm between output files, with a little bit of remapping applied to find type information. Let’s look at another example that appears unintuitive through the lens of the simple model, but makes perfect sense with the robust model: // @moduleResolution: node16 // @rootDir: src // @outDir: dist // @Filename: src/math.mts export function add(a: number, b: number) { return a + b; } // @Filename: src/main.mts import { add } from "./math.mjs"; add(1, 2); Node.js ESM `import` declarations use a strict module resolution algorithm that requires relative paths to include file extensions. When we only think about input files, it’s a little strange that `"./math.mjs"` seems to resolve to `math.mts`. Since we’re using an `outDir` to put compiled outputs in a different directory, `math.mjs` doesn’t even exist next to `main.mts`! Why should this resolve? With our new mental model, it’s no problem: Understanding this mental model may not immediately eliminate the strangeness of seeing output file extensions in input files, and it’s natural to think in terms of shortcuts: _`"./math.mjs"` refers to the input file `math.mts`. I have to write the output extension, but the compiler knows to look for `.mts` when I write `.mjs`._ This shortcut is even how the compiler works internally, but the more robust mental model explains _why_ module resolution in TypeScript works this way: given the constraint that the module specifier in the output file will be the same as the module specifier in the input file, this is the only process that accomplishes our two goals of validating output files and assigning types. ### The role of declaration files In the previous example, we saw the “remapping” part of module resolution working between input and output files. But what happens when we import library code? Even if the library was written in TypeScript, it may not have published its source code. If we can’t rely on mapping the library’s JavaScript files back to a TypeScript file, we can verify that our import works at runtime, but how do we accomplish our second goal of assigning types? This is where declaration files (`.d.ts`, `.d.mts`, etc.) come into play. The best way to understand how declaration files are interpreted is to understand where they come from. When you run `tsc --declaration` on an input file, you get one output JavaScript file and one output declaration file: Because of this relationship, the compiler _assumes_ that wherever it sees a declaration file, there is a corresponding JavaScript file that is perfectly described by the type information in the declaration file. For performance reasons, in every module resolution mode, the compiler always looks for TypeScript and declaration files first, and if it finds one, it doesn’t continue looking for the corresponding JavaScript file. If it finds a TypeScript input file, it knows a JavaScript file _will_ exist after compilation, and if it finds a declaration file, it knows a compilation (perhaps someone else’s) already happened and created a JavaScript file at the same time as the declaration file. The declaration file tells the compiler not only that a JavaScript file exists, but also what its name and extension are: Declaration file extension | JavaScript file extension | TypeScript file extension ---|---|--- `.d.ts` | `.js` | `.ts` `.d.ts` | `.js` | `.tsx` `.d.mts` | `.mjs` | `.mts` `.d.cts` | `.cjs` | `.cts` `.d.*.ts` | `.*` | The last row expresses that non-JS files can be typed with the `allowArbitraryExtensions` compiler option to support cases where the module system supports importing non-JS files as JavaScript objects. For example, a file named `styles.css` can be represented by a declaration file named `styles.d.css.ts`. > “But wait! Plenty of declaration files are written by hand, _not_ generated > by `tsc`. Ever heard of DefinitelyTyped?” you might object. And it’s > true—hand-writing declaration files, or even moving/copying/renaming them to > represent outputs of an external build tool, is a dangerous, error-prone > venture. DefinitelyTyped contributors and authors of typed libraries not > using `tsc` to generate both JavaScript and declaration files should ensure > that every JavaScript file has a sibling declaration file with the same name > and matching extension. Breaking from this structure can lead to false- > positive TypeScript errors for end users. The npm package > [`@arethetypeswrong/cli`](https://www.npmjs.com/package/@arethetypeswrong/cli) > can help catch and explain these errors before they’re published. ### Module resolution for bundlers, TypeScript runtimes, and Node.js loaders So far, we’ve really emphasized the distinction between _input files_ and _output files_. Recall that when specifying a file extension on a relative module specifier, TypeScript typically makes you use the _output_ file extension: // @Filename: src/math.ts export function add(a: number, b: number) { return a + b; } // @Filename: src/main.ts import { add } from "./math.ts"; // ^^^^^^^^^^^ // An import path can only end with a '.ts' extension when 'allowImportingTsExtensions' is enabled. This restriction applies since TypeScript won’t rewrite the extension to `.js`, and if `"./math.ts"` appears in an output JS file, that import won’t resolve to another JS file at runtime. TypeScript really wants to prevent you from generating an unsafe output JS file. But what if there _is_ no output JS file? What if you’re in one of these situations: * You’re bundling this code, the bundler is configured to transpile TypeScript files in-memory, and it will eventually consume and erase all the imports you’ve written to produce a bundle. * You’re running this code directly in a TypeScript runtime like Deno or Bun. * You’re using `ts-node`, `tsx`, or another transpiling loader for Node. In these cases, you can turn on `noEmit` (or `emitDeclarationOnly`) and `allowImportingTsExtensions` to disable emitting unsafe JavaScript files and silence the error on `.ts`-extensioned imports. With or without `allowImportingTsExtensions`, it’s still important to pick the most appropriate `moduleResolution` setting for the module resolution host. For bundlers and the Bun runtime, it’s `bundler`. These module resolvers were inspired by Node.js, but didn’t adopt the strict ESM resolution algorithm that disables extension searching that Node.js applies to imports. The `bundler` module resolution setting reflects this, enabling `package.json` `"exports"` support like `node16`—`nodenext`, while always allowing extensionless imports. See [_Choosing compiler options_](guides/choosing-compiler-options) for more guidance. ### Module resolution for libraries When compiling an app, you choose the `moduleResolution` option for a TypeScript project based on who the module resolution host is. When compiling a library, you don’t know where the output code will run, but you’d like it to run in as many places as possible. Using `"module": "node18"` (along with the implied [`"moduleResolution": "node16"`](reference#node16-nodenext-1)) is the best bet for maximizing the compatibility of the output JavaScript’s module specifiers, since it will force you to comply with Node.js’s stricter rules for `import` module resolution. Let’s look at what would happen if a library were to compile with `"moduleResolution": "bundler"` (or worse, `"node10"`): export * from "./utils"; Assuming `./utils.ts` (or `./utils/index.ts`) exists, a bundler would be fine with this code, so `"moduleResolution": "bundler"` doesn’t complain. Compiled with `"module": "esnext"`, the output JavaScript for this export statement will look exactly the same as the input. If that JavaScript were published to npm, it would be usable by projects that use a bundler, but it would cause an error when run in Node.js: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '.../node_modules/dependency/utils' imported from .../node_modules/dependency/index.js Did you mean to import ./utils.js? On the other hand, if we had written: export * from "./utils.js"; This would produce output that works both in Node.js _and_ in bundlers. In short, `"moduleResolution": "bundler"` is infectious, allowing code that only works in bundlers to be produced. Likewise, `"moduleResolution": "nodenext"` is only checking that the output works in Node.js, but in most cases, module code that works in Node.js will work in other runtimes and in bundlers. Of course, this guidance can only apply in cases where the library ships outputs from `tsc`. If the library is being bundled _before_ shipping, `"moduleResolution": "bundler"` may be acceptable. Any build tool that changes the module format or module specifiers to produce the final build of the library bears the responsibility of ensuring the safety and compatibility of the product’s module code, and `tsc` can no longer contribute to that task, since it can’t know what module code will exist at runtime. * * * 1. In Node.js v22.12.0 and later, a `require` of an ES module is allowed, but only if the resolved module and its top-level imports don’t use top-level `await`. TypeScript does not try to enforce this rule, as it lacks the ability to tell from a declaration file whether the corresponding JavaScript file contains top-level `await`.↩ ##### On this page * Scripts and modules in JavaScript * TypeScript’s job concerning modules * Who is the host? * The module output format * Module format detection * Input module syntax * ESM and CJS interoperability * Module specifiers are not transformed by default * Module resolution * Module resolution is host-defined * TypeScript imitates the host’s module resolution, but with types * The role of declaration files * Module resolution for bundlers, TypeScript runtimes, and Node.js loaders * Module resolution for libraries ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/modules-reference/Theory.md) ❤ Contributors to this page: AB Last updated: Mar 11, 2025 # Namespaces and Modules Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) # Namespaces and Modules This post outlines the various ways to organize your code using modules and namespaces in TypeScript. We’ll also go over some advanced topics of how to use namespaces and modules, and address some common pitfalls when using them in TypeScript. See the [Modules](modules) documentation for more information about ES Modules. See the [Namespaces](namespaces) documentation for more information about TypeScript namespaces. Note: In _very_ old versions of TypeScript namespaces were called ‘Internal Modules’, these pre-date JavaScript module systems. ## Using Modules Modules can contain both code and declarations. Modules also have a dependency on a module loader (such as CommonJs/Require.js) or a runtime which supports ES Modules. Modules provide for better code reuse, stronger isolation and better tooling support for bundling. It is also worth noting that, for Node.js applications, modules are the default and **we recommended modules over namespaces in modern code**. Starting with ECMAScript 2015, modules are native part of the language, and should be supported by all compliant engine implementations. Thus, for new projects modules would be the recommended code organization mechanism. ## Using Namespaces Namespaces are a TypeScript-specific way to organize code. Namespaces are simply named JavaScript objects in the global namespace. This makes namespaces a very simple construct to use. Unlike modules, they can span multiple files, and can be concatenated using [`outFile`](../../tsconfig#outFile). Namespaces can be a good way to structure your code in a Web Application, with all dependencies included as ` Open `greeter.html` in the browser to run your first simple TypeScript web application! Optional: Open `greeter.ts` in Visual Studio, or copy the code into the TypeScript playground. You can hover over identifiers to see their types. Notice that in some cases these types are inferred automatically for you. Re- type the last line, and see completion lists and parameter help based on the types of the DOM elements. Put your cursor on the reference to the greeter function, and hit F12 to go to its definition. Notice, too, that you can right-click on a symbol and use refactoring to rename it. The type information provided works together with the tools to work with JavaScript at application scale. For more examples of what’s possible in TypeScript, see the Samples section of the website. ##### On this page * Installing TypeScript * Building your first TypeScript file * Compiling your code * Type annotations * Interfaces * Classes * Running your TypeScript web app ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/tutorials/TypeScript%20Tooling%20in%205%20minutes.md) ❤ Contributors to this page: OT H DS M Last updated: Mar 11, 2025 # Utility Types Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) # Utility Types TypeScript provides several utility types to facilitate common type transformations. These utilities are available globally. ## `Awaited` > Released: [4.5](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-4-5.html#the-awaited-type-and-promise-improvements) This type is meant to model operations like `await` in `async` functions, or the `.then()` method on `Promise`s - specifically, the way that they recursively unwrap `Promise`s. ##### Example type A = Awaited>;   type B = Awaited>>;   type C = Awaited>; ## `Partial` > Released: > [2.1](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-2-1.html#partial-readonly-record-and-pick) Constructs a type with all properties of `Type` set to optional. This utility will return a type that represents all subsets of a given type. ##### Example interface Todo { title: string; description: string; }   function updateTodo(todo: Todo, fieldsToUpdate: Partial) { return { ...todo, ...fieldsToUpdate }; }   const todo1 = { title: "organize desk", description: "clear clutter", };   const todo2 = updateTodo(todo1, { description: "throw out trash", }); ## `Required` > Released: > [2.8](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-2-8.html#improved-control-over-mapped-type-modifiers) Constructs a type consisting of all properties of `Type` set to required. The opposite of `Partial`. ##### Example interface Props { a?: number; b?: string; }   const obj: Props = { a: 5 };   const obj2: Required = { a: 5 }; ## `Readonly` > Released: > [2.1](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-2-1.html#partial-readonly-record-and-pick) Constructs a type with all properties of `Type` set to `readonly`, meaning the properties of the constructed type cannot be reassigned. ##### Example interface Todo { title: string; }   const todo: Readonly = { title: "Delete inactive users", };   todo.title = "Hello"; This utility is useful for representing assignment expressions that will fail at runtime (i.e. when attempting to reassign properties of a [frozen object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)). ##### `Object.freeze` function freeze(obj: Type): Readonly; ## `Record` > Released: > [2.1](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-2-1.html#partial-readonly-record-and-pick) Constructs an object type whose property keys are `Keys` and whose property values are `Type`. This utility can be used to map the properties of a type to another type. ##### Example type CatName = "miffy" | "boris" | "mordred";   interface CatInfo { age: number; breed: string; }   const cats: Record = { miffy: { age: 10, breed: "Persian" }, boris: { age: 5, breed: "Maine Coon" }, mordred: { age: 16, breed: "British Shorthair" }, };   cats.boris; ## `Pick` > Released: > [2.1](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-2-1.html#partial-readonly-record-and-pick) Constructs a type by picking the set of properties `Keys` (string literal or union of string literals) from `Type`. ##### Example interface Todo { title: string; description: string; completed: boolean; }   type TodoPreview = Pick;   const todo: TodoPreview = { title: "Clean room", completed: false, };   todo; ## `Omit` > Released: > [3.5](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-3-5.html#the-omit-helper-type) Constructs a type by picking all properties from `Type` and then removing `Keys` (string literal or union of string literals). The opposite of `Pick`. ##### Example interface Todo { title: string; description: string; completed: boolean; createdAt: number; }   type TodoPreview = Omit;   const todo: TodoPreview = { title: "Clean room", completed: false, createdAt: 1615544252770, };   todo;   type TodoInfo = Omit;   const todoInfo: TodoInfo = { title: "Pick up kids", description: "Kindergarten closes at 5pm", };   todoInfo; ## `Exclude` > Released: > [2.8](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-2-8.html#predefined-conditional-types) Constructs a type by excluding from `UnionType` all union members that are assignable to `ExcludedMembers`. ##### Example type T0 = Exclude<"a" | "b" | "c", "a">; type T1 = Exclude<"a" | "b" | "c", "a" | "b">; type T2 = Exclude void), Function>;   type Shape = | { kind: "circle"; radius: number } | { kind: "square"; x: number } | { kind: "triangle"; x: number; y: number };   type T3 = Exclude ## `Extract` > Released: > [2.8](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-2-8.html#predefined-conditional-types) Constructs a type by extracting from `Type` all union members that are assignable to `Union`. ##### Example type T0 = Extract<"a" | "b" | "c", "a" | "f">; type T1 = Extract void), Function>;   type Shape = | { kind: "circle"; radius: number } | { kind: "square"; x: number } | { kind: "triangle"; x: number; y: number };   type T2 = Extract ## `NonNullable` > Released: > [2.8](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-2-8.html#predefined-conditional-types) Constructs a type by excluding `null` and `undefined` from `Type`. ##### Example type T0 = NonNullable; type T1 = NonNullable; ## `Parameters` > Released: > [3.1](https://github.com/microsoft/TypeScript/pull/26243) Constructs a tuple type from the types used in the parameters of a function type `Type`. For overloaded functions, this will be the parameters of the _last_ signature; see [Inferring Within Conditional Types](2/conditional-types#inferring-within- conditional-types). ##### Example declare function f1(arg: { a: number; b: string }): void;   type T0 = Parameters<() => string>; type T1 = Parameters<(s: string) => void>; type T2 = Parameters<(arg: T) => T>; type T3 = Parameters; type T4 = Parameters; type T5 = Parameters; type T6 = Parameters; type T7 = Parameters; ## `ConstructorParameters` > Released: > [3.1](https://github.com/microsoft/TypeScript/pull/26243) Constructs a tuple or array type from the types of a constructor function type. It produces a tuple type with all the parameter types (or the type `never` if `Type` is not a function). ##### Example type T0 = ConstructorParameters; type T1 = ConstructorParameters; type T2 = ConstructorParameters; class C { constructor(a: number, b: string) {} } type T3 = ConstructorParameters; type T4 = ConstructorParameters;   type T5 = ConstructorParameters; ## `ReturnType` > Released: > [2.8](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-2-8.html#predefined-conditional-types) Constructs a type consisting of the return type of function `Type`. For overloaded functions, this will be the return type of the _last_ signature; see [Inferring Within Conditional Types](2/conditional- types#inferring-within-conditional-types). ##### Example declare function f1(): { a: number; b: string };   type T0 = ReturnType<() => string>; type T1 = ReturnType<(s: string) => void>; type T2 = ReturnType<() => T>; type T3 = ReturnType<() => T>; type T4 = ReturnType; type T5 = ReturnType; type T6 = ReturnType; type T7 = ReturnType; type T8 = ReturnType; ## `InstanceType` > Released: > [2.8](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-2-8.html#predefined-conditional-types) Constructs a type consisting of the instance type of a constructor function in `Type`. ##### Example class C { x = 0; y = 0; }   type T0 = InstanceType; type T1 = InstanceType; type T2 = InstanceType; type T3 = InstanceType; type T4 = InstanceType; ## `NoInfer` > Released: > [5.4](https://www.typescriptlang.org/docs/handbook/release- > notes/typescript-5-4.html#the-noinfer-utility-type) Blocks inferences to the contained type. Other than blocking inferences, `NoInfer` is identical to `Type`. ##### Example function createStreetLight( colors: C[], defaultColor?: NoInfer, ) { // ... } createStreetLight(["red", "yellow", "green"], "red"); // OK createStreetLight(["red", "yellow", "green"], "blue"); // Error ## `ThisParameterType` > Released: > [3.3](https://github.com/microsoft/TypeScript/pull/28920) Extracts the type of the [this](functions#this-parameters) parameter for a function type, or [unknown](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-0.html#new-unknown-top-type) if the function type has no `this` parameter. ##### Example function toHex(this: Number) { return this.toString(16); }   function numberToString(n: ThisParameterType) { return toHex.apply(n); } ## `OmitThisParameter` > Released: > [3.3](https://github.com/microsoft/TypeScript/pull/28920) Removes the [`this`](functions#this-parameters) parameter from `Type`. If `Type` has no explicitly declared `this` parameter, the result is simply `Type`. Otherwise, a new function type with no `this` parameter is created from `Type`. Generics are erased and only the last overload signature is propagated into the new function type. ##### Example function toHex(this: Number) { return this.toString(16); }   const fiveToHex: OmitThisParameter = toHex.bind(5);   console.log(fiveToHex()); ## `ThisType` > Released: > [2.3](https://github.com/microsoft/TypeScript/pull/14141) This utility does not return a transformed type. Instead, it serves as a marker for a contextual [`this`](functions#this) type. Note that the [`noImplicitThis`](../../tsconfig#noImplicitThis) flag must be enabled to use this utility. ##### Example type ObjectDescriptor = { data?: D; methods?: M & ThisType; // Type of 'this' in methods is D & M };   function makeObject(desc: ObjectDescriptor): D & M { let data: object = desc.data || {}; let methods: object = desc.methods || {}; return { ...data, ...methods } as D & M; }   let obj = makeObject({ data: { x: 0, y: 0 }, methods: { moveBy(dx: number, dy: number) { this.x += dx; // Strongly typed this this.y += dy; // Strongly typed this }, }, });   obj.x = 10; obj.y = 20; obj.moveBy(5, 5); In the example above, the `methods` object in the argument to `makeObject` has a contextual type that includes `ThisType` and therefore the type of [this](functions#this) in methods within the `methods` object is `{ x: number, y: number } & { moveBy(dx: number, dy: number): void }`. Notice how the type of the `methods` property simultaneously is an inference target and a source for the `this` type in methods. The `ThisType` marker interface is simply an empty interface declared in `lib.d.ts`. Beyond being recognized in the contextual type of an object literal, the interface acts like any empty interface. ## Intrinsic String Manipulation Types ### `Uppercase` ### `Lowercase` ### `Capitalize` ### `Uncapitalize` To help with string manipulation around template string literals, TypeScript includes a set of types which can be used in string manipulation within the type system. You can find those in the [Template Literal Types](2/template- literal-types#uppercasestringtype) documentation. ##### On this page * Awaited * Partial * Required * Readonly * Record * Pick * Omit * Exclude * Extract * NonNullable * Parameters * ConstructorParameters * ReturnType * InstanceType * NoInfer * ThisParameterType * OmitThisParameter * ThisType * Intrinsic String Manipulation Types * Uppercase * Lowercase * Capitalize * Uncapitalize ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/reference/Utility%20Types.md) ❤ Contributors to this page: C OT B JB HX 34+ Last updated: Mar 11, 2025 # Variable Declaration Was this page helpful? * Get Started * [TS for the New Programmer](typescript-from-scratch) * [TypeScript for JS Programmers](typescript-in-5-minutes) * [TS for Java/C# Programmers](typescript-in-5-minutes-oop) * [TS for Functional Programmers](typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](typescript-tooling-in-5-minutes) * Handbook * [The TypeScript Handbook](intro) * [The Basics](2/basic-types) * [Everyday Types](2/everyday-types) * [Narrowing](2/narrowing) * [More on Functions](2/functions) * [Object Types](2/objects) * Type Manipulation * [Creating Types from Types](2/types-from-types) * [Generics](2/generics) * [Keyof Type Operator](2/keyof-types) * [Typeof Type Operator](2/typeof-types) * [Indexed Access Types](2/indexed-access-types) * [Conditional Types](2/conditional-types) * [Mapped Types](2/mapped-types) * [Template Literal Types](2/template-literal-types) * [Classes](2/classes) * [Modules](2/modules) * Reference * [Utility Types](utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](decorators) * [Declaration Merging](declaration-merging) * [Enums](enums) * [Iterators and Generators](iterators-and-generators) * [JSX](jsx) * [Mixins](mixins) * [Namespaces](namespaces) * [Namespaces and Modules](namespaces-and-modules) * [Symbols](symbols) * [Triple-Slash Directives](triple-slash-directives) * [Type Compatibility](type-compatibility) * [Type Inference](type-inference) * [Variable Declaration](variable-declarations) * Modules Reference * [Introduction](modules/introduction) * [Theory](modules/theory) * Guides * [Choosing Compiler Options](modules/guides/choosing-compiler-options) * [Reference](modules/reference) * Appendices * [ESM/CJS Interoperability](modules/appendices/esm-cjs-interop) * Tutorials * [ASP.NET Core](asp-net-core) * [Gulp](gulp) * [DOM Manipulation](dom-manipulation) * [Migrating from JavaScript](migrating-from-javascript) * [Using Babel with TypeScript](babel-with-typescript) * What's New * [TypeScript 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) * [TypeScript 5.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) * [TypeScript 5.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html) * [TypeScript 5.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html) * [TypeScript 5.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-4.html) * [TypeScript 5.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-3.html) * [TypeScript 5.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-2.html) * [TypeScript 5.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-1.html) * [TypeScript 5.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html) * [TypeScript 4.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html) * [TypeScript 4.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-8.html) * [TypeScript 4.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html) * [TypeScript 4.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-6.html) * [TypeScript 4.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html) * [TypeScript 4.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html) * [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html) * [TypeScript 4.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html) * [TypeScript 4.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html) * [TypeScript 4.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html) * [TypeScript 3.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html) * [TypeScript 3.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html) * [TypeScript 3.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) * [TypeScript 3.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-6.html) * [TypeScript 3.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html) * [TypeScript 3.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html) * [TypeScript 3.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-3.html) * [TypeScript 3.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html) * [TypeScript 3.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html) * [TypeScript 3.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html) * [TypeScript 2.9](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html) * [TypeScript 2.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html) * [TypeScript 2.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html) * [TypeScript 2.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html) * [TypeScript 2.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-5.html) * [TypeScript 2.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-4.html) * [TypeScript 2.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html) * [TypeScript 2.2](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html) * [TypeScript 2.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html) * [TypeScript 2.0](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html) * [TypeScript 1.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html) * [TypeScript 1.7](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html) * [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-6.html) * [TypeScript 1.5](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-5.html) * [TypeScript 1.4](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-4.html) * [TypeScript 1.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-3.html) * [TypeScript 1.1](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-1.html) * Declaration Files * [Introduction](declaration-files/introduction) * [Declaration Reference](declaration-files/by-example) * [Library Structures](declaration-files/library-structures) * .d.ts Templates * [Modules .d.ts](declaration-files/templates/module-d-ts) * [Module: Plugin](declaration-files/templates/module-plugin-d-ts) * [Module: Class](declaration-files/templates/module-class-d-ts) * [Module: Function](declaration-files/templates/module-function-d-ts) * [Global .d.ts](declaration-files/templates/global-d-ts) * [Global: Modifying Module](declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](declaration-files/do-s-and-don-ts) * [Deep Dive](declaration-files/deep-dive) * [Publishing](declaration-files/publishing) * [Consumption](declaration-files/consumption) * JavaScript * [JS Projects Utilizing TypeScript](intro-to-js-ts) * [Type Checking JavaScript Files](type-checking-javascript-files) * [JSDoc Reference](jsdoc-supported-types) * [Creating .d.ts Files from .js files](declaration-files/dts-from-js) * Project Configuration * [What is a tsconfig.json](tsconfig-json) * [Compiler Options in MSBuild](compiler-options-in-msbuild) * [TSConfig Reference](../../tsconfig/index) * [tsc CLI Options](compiler-options) * [Project References](project-references) * [Integrating with Build Tools](integrating-with-build-tools) * [Configuring Watch](configuring-watch) * [Nightly Builds](nightly-builds) # Variable Declaration `let` and `const` are two relatively new concepts for variable declarations in JavaScript. [As we mentioned earlier](basic-types#a-note-about-let), `let` is similar to `var` in some respects, but allows users to avoid some of the common “gotchas” that users run into in JavaScript. `const` is an augmentation of `let` in that it prevents re-assignment to a variable. With TypeScript being an extension of JavaScript, the language naturally supports `let` and `const`. Here we’ll elaborate more on these new declarations and why they’re preferable to `var`. If you’ve used JavaScript offhandedly, the next section might be a good way to refresh your memory. If you’re intimately familiar with all the quirks of `var` declarations in JavaScript, you might find it easier to skip ahead. ## `var` declarations Declaring a variable in JavaScript has always traditionally been done with the `var` keyword. var a = 10; As you might’ve figured out, we just declared a variable named `a` with the value `10`. We can also declare a variable inside of a function: function f() { var message = "Hello, world!"; return message; } and we can also access those same variables within other functions: function f() { var a = 10; return function g() { var b = a + 1; return b; }; } var g = f(); g(); // returns '11' In this above example, `g` captured the variable `a` declared in `f`. At any point that `g` gets called, the value of `a` will be tied to the value of `a` in `f`. Even if `g` is called once `f` is done running, it will be able to access and modify `a`. function f() { var a = 1; a = 2; var b = g(); a = 3; return b; function g() { return a; } } f(); // returns '2' ### Scoping rules `var` declarations have some odd scoping rules for those used to other languages. Take the following example: function f(shouldInitialize: boolean) { if (shouldInitialize) { var x = 10; } return x; } f(true); // returns '10' f(false); // returns 'undefined' Some readers might do a double-take at this example. The variable `x` was declared _within the`if` block_, and yet we were able to access it from outside that block. That’s because `var` declarations are accessible anywhere within their containing function, module, namespace, or global scope - all which we’ll go over later on - regardless of the containing block. Some people call this _`var`-scoping_ or _function-scoping_. Parameters are also function scoped. These scoping rules can cause several types of mistakes. One problem they exacerbate is the fact that it is not an error to declare the same variable multiple times: function sumMatrix(matrix: number[][]) { var sum = 0; for (var i = 0; i < matrix.length; i++) { var currentRow = matrix[i]; for (var i = 0; i < currentRow.length; i++) { sum += currentRow[i]; } } return sum; } Maybe it was easy to spot out for some experienced JavaScript developers, but the inner `for`-loop will accidentally overwrite the variable `i` because `i` refers to the same function-scoped variable. As experienced developers know by now, similar sorts of bugs slip through code reviews and can be an endless source of frustration. ### Variable capturing quirks Take a quick second to guess what the output of the following snippet is: for (var i = 0; i < 10; i++) { setTimeout(function () { console.log(i); }, 100 * i); } For those unfamiliar, `setTimeout` will try to execute a function after a certain number of milliseconds (though waiting for anything else to stop running). Ready? Take a look: 10 10 10 10 10 10 10 10 10 10 Many JavaScript developers are intimately familiar with this behavior, but if you’re surprised, you’re certainly not alone. Most people expect the output to be 0 1 2 3 4 5 6 7 8 9 Remember what we mentioned earlier about variable capturing? Every function expression we pass to `setTimeout` actually refers to the same `i` from the same scope. Let’s take a minute to consider what that means. `setTimeout` will run a function after some number of milliseconds, _but only_ after the `for` loop has stopped executing; By the time the `for` loop has stopped executing, the value of `i` is `10`. So each time the given function gets called, it will print out `10`! A common work around is to use an IIFE - an Immediately Invoked Function Expression - to capture `i` at each iteration: for (var i = 0; i < 10; i++) { // capture the current state of 'i' // by invoking a function with its current value (function (i) { setTimeout(function () { console.log(i); }, 100 * i); })(i); } This odd-looking pattern is actually pretty common. The `i` in the parameter list actually shadows the `i` declared in the `for` loop, but since we named them the same, we didn’t have to modify the loop body too much. ## `let` declarations By now you’ve figured out that `var` has some problems, which is precisely why `let` statements were introduced. Apart from the keyword used, `let` statements are written the same way `var` statements are. let hello = "Hello!"; The key difference is not in the syntax, but in the semantics, which we’ll now dive into. ### Block-scoping When a variable is declared using `let`, it uses what some call _lexical- scoping_ or _block-scoping_. Unlike variables declared with `var` whose scopes leak out to their containing function, block-scoped variables are not visible outside of their nearest containing block or `for`-loop. function f(input: boolean) { let a = 100; if (input) { // Still okay to reference 'a' let b = a + 1; return b; } // Error: 'b' doesn't exist here return b; } Here, we have two local variables `a` and `b`. `a`’s scope is limited to the body of `f` while `b`’s scope is limited to the containing `if` statement’s block. Variables declared in a `catch` clause also have similar scoping rules. try { throw "oh no!"; } catch (e) { console.log("Oh well."); } // Error: 'e' doesn't exist here console.log(e); Another property of block-scoped variables is that they can’t be read or written to before they’re actually declared. While these variables are “present” throughout their scope, all points up until their declaration are part of their _temporal dead zone_. This is just a sophisticated way of saying you can’t access them before the `let` statement, and luckily TypeScript will let you know that. a++; // illegal to use 'a' before it's declared; let a; Something to note is that you can still _capture_ a block-scoped variable before it’s declared. The only catch is that it’s illegal to call that function before the declaration. If targeting ES2015, a modern runtime will throw an error; however, right now TypeScript is permissive and won’t report this as an error. function foo() { // okay to capture 'a' return a; } // illegal call 'foo' before 'a' is declared // runtimes should throw an error here foo(); let a; For more information on temporal dead zones, see relevant content on the [Mozilla Developer Network](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone_and_errors_with_let). ### Re-declarations and Shadowing With `var` declarations, we mentioned that it didn’t matter how many times you declared your variables; you just got one. function f(x) { var x; var x; if (true) { var x; } } In the above example, all declarations of `x` actually refer to the _same_ `x`, and this is perfectly valid. This often ends up being a source of bugs. Thankfully, `let` declarations are not as forgiving. let x = 10; let x = 20; // error: can't re-declare 'x' in the same scope The variables don’t necessarily need to both be block-scoped for TypeScript to tell us that there’s a problem. function f(x) { let x = 100; // error: interferes with parameter declaration } function g() { let x = 100; var x = 100; // error: can't have both declarations of 'x' } That’s not to say that a block-scoped variable can never be declared with a function-scoped variable. The block-scoped variable just needs to be declared within a distinctly different block. function f(condition, x) { if (condition) { let x = 100; return x; } return x; } f(false, 0); // returns '0' f(true, 0); // returns '100' The act of introducing a new name in a more nested scope is called _shadowing_. It is a bit of a double-edged sword in that it can introduce certain bugs on its own in the event of accidental shadowing, while also preventing certain bugs. For instance, imagine we had written our earlier `sumMatrix` function using `let` variables. function sumMatrix(matrix: number[][]) { let sum = 0; for (let i = 0; i < matrix.length; i++) { var currentRow = matrix[i]; for (let i = 0; i < currentRow.length; i++) { sum += currentRow[i]; } } return sum; } This version of the loop will actually perform the summation correctly because the inner loop’s `i` shadows `i` from the outer loop. Shadowing should _usually_ be avoided in the interest of writing clearer code. While there are some scenarios where it may be fitting to take advantage of it, you should use your best judgement. ### Block-scoped variable capturing When we first touched on the idea of variable capturing with `var` declaration, we briefly went into how variables act once captured. To give a better intuition of this, each time a scope is run, it creates an “environment” of variables. That environment and its captured variables can exist even after everything within its scope has finished executing. function theCityThatAlwaysSleeps() { let getCity; if (true) { let city = "Seattle"; getCity = function () { return city; }; } return getCity(); } Because we’ve captured `city` from within its environment, we’re still able to access it despite the fact that the `if` block finished executing. Recall that with our earlier `setTimeout` example, we ended up needing to use an IIFE to capture the state of a variable for every iteration of the `for` loop. In effect, what we were doing was creating a new variable environment for our captured variables. That was a bit of a pain, but luckily, you’ll never have to do that again in TypeScript. `let` declarations have drastically different behavior when declared as part of a loop. Rather than just introducing a new environment to the loop itself, these declarations sort of create a new scope _per iteration_. Since this is what we were doing anyway with our IIFE, we can change our old `setTimeout` example to just use a `let` declaration. for (let i = 0; i < 10; i++) { setTimeout(function () { console.log(i); }, 100 * i); } and as expected, this will print out 0 1 2 3 4 5 6 7 8 9 ## `const` declarations `const` declarations are another way of declaring variables. const numLivesForCat = 9; They are like `let` declarations but, as their name implies, their value cannot be changed once they are bound. In other words, they have the same scoping rules as `let`, but you can’t re-assign to them. This should not be confused with the idea that the values they refer to are _immutable_. const numLivesForCat = 9; const kitty = { name: "Aurora", numLives: numLivesForCat, }; // Error kitty = { name: "Danielle", numLives: numLivesForCat, }; // all "okay" kitty.name = "Rory"; kitty.name = "Kitty"; kitty.name = "Cat"; kitty.numLives--; Unless you take specific measures to avoid it, the internal state of a `const` variable is still modifiable. Fortunately, TypeScript allows you to specify that members of an object are `readonly`. The [chapter on Interfaces](interfaces) has the details. ## `let` vs. `const` Given that we have two types of declarations with similar scoping semantics, it’s natural to find ourselves asking which one to use. Like most broad questions, the answer is: it depends. Applying the [principle of least privilege](https://wikipedia.org/wiki/Principle_of_least_privilege), all declarations other than those you plan to modify should use `const`. The rationale is that if a variable didn’t need to get written to, others working on the same codebase shouldn’t automatically be able to write to the object, and will need to consider whether they really need to reassign to the variable. Using `const` also makes code more predictable when reasoning about flow of data. Use your best judgement, and if applicable, consult the matter with the rest of your team. The majority of this handbook uses `let` declarations. ## Destructuring Another ECMAScript 2015 feature that TypeScript has is destructuring. For a complete reference, see [the article on the Mozilla Developer Network](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment). In this section, we’ll give a short overview. ### Array destructuring The simplest form of destructuring is array destructuring assignment: let input = [1, 2]; let [first, second] = input; console.log(first); // outputs 1 console.log(second); // outputs 2 This creates two new variables named `first` and `second`. This is equivalent to using indexing, but is much more convenient: first = input[0]; second = input[1]; Destructuring works with already-declared variables as well: // swap variables [first, second] = [second, first]; And with parameters to a function: function f([first, second]: [number, number]) { console.log(first); console.log(second); } f([1, 2]); You can create a variable for the remaining items in a list using the syntax `...`: let [first, ...rest] = [1, 2, 3, 4]; console.log(first); // outputs 1 console.log(rest); // outputs [ 2, 3, 4 ] Of course, since this is JavaScript, you can just ignore trailing elements you don’t care about: let [first] = [1, 2, 3, 4]; console.log(first); // outputs 1 Or other elements: let [, second, , fourth] = [1, 2, 3, 4]; console.log(second); // outputs 2 console.log(fourth); // outputs 4 ### Tuple destructuring Tuples may be destructured like arrays; the destructuring variables get the types of the corresponding tuple elements: let tuple: [number, string, boolean] = [7, "hello", true]; let [a, b, c] = tuple; // a: number, b: string, c: boolean It’s an error to destructure a tuple beyond the range of its elements: let [a, b, c, d] = tuple; // Error, no element at index 3 As with arrays, you can destructure the rest of the tuple with `...`, to get a shorter tuple: let [a, ...bc] = tuple; // bc: [string, boolean] let [a, b, c, ...d] = tuple; // d: [], the empty tuple Or ignore trailing elements, or other elements: let [a] = tuple; // a: number let [, b] = tuple; // b: string ### Object destructuring You can also destructure objects: let o = { a: "foo", b: 12, c: "bar", }; let { a, b } = o; This creates new variables `a` and `b` from `o.a` and `o.b`. Notice that you can skip `c` if you don’t need it. Like array destructuring, you can have assignment without declaration: ({ a, b } = { a: "baz", b: 101 }); Notice that we had to surround this statement with parentheses. JavaScript normally parses a `{` as the start of block. You can create a variable for the remaining items in an object using the syntax `...`: let { a, ...passthrough } = o; let total = passthrough.b + passthrough.c.length; #### Property renaming You can also give different names to properties: let { a: newName1, b: newName2 } = o; Here the syntax starts to get confusing. You can read `a: newName1` as ”`a` as `newName1`”. The direction is left-to-right, as if you had written: let newName1 = o.a; let newName2 = o.b; Confusingly, the colon here does _not_ indicate the type. The type, if you specify it, still needs to be written after the entire destructuring: let { a: newName1, b: newName2 }: { a: string; b: number } = o; #### Default values Default values let you specify a default value in case a property is undefined: function keepWholeObject(wholeObject: { a: string; b?: number }) { let { a, b = 1001 } = wholeObject; } In this example the `b?` indicates that `b` is optional, so it may be `undefined`. `keepWholeObject` now has a variable for `wholeObject` as well as the properties `a` and `b`, even if `b` is undefined. ## Function declarations Destructuring also works in function declarations. For simple cases this is straightforward: type C = { a: string; b?: number }; function f({ a, b }: C): void { // ... } But specifying defaults is more common for parameters, and getting defaults right with destructuring can be tricky. First of all, you need to remember to put the pattern before the default value. function f({ a = "", b = 0 } = {}): void { // ... } f(); > The snippet above is an example of type inference, explained earlier in the > handbook. Then, you need to remember to give a default for optional properties on the destructured property instead of the main initializer. Remember that `C` was defined with `b` optional: function f({ a, b = 0 } = { a: "" }): void { // ... } f({ a: "yes" }); // ok, default b = 0 f(); // ok, default to { a: "" }, which then defaults b = 0 f({}); // error, 'a' is required if you supply an argument Use destructuring with care. As the previous example demonstrates, anything but the simplest destructuring expression is confusing. This is especially true with deeply nested destructuring, which gets _really_ hard to understand even without piling on renaming, default values, and type annotations. Try to keep destructuring expressions small and simple. You can always write the assignments that destructuring would generate yourself. ## Spread The spread operator is the opposite of destructuring. It allows you to spread an array into another array, or an object into another object. For example: let first = [1, 2]; let second = [3, 4]; let bothPlus = [0, ...first, ...second, 5]; This gives bothPlus the value `[0, 1, 2, 3, 4, 5]`. Spreading creates a shallow copy of `first` and `second`. They are not changed by the spread. You can also spread objects: let defaults = { food: "spicy", price: "$$", ambiance: "noisy" }; let search = { ...defaults, food: "rich" }; Now `search` is `{ food: "rich", price: "$$", ambiance: "noisy" }`. Object spreading is more complex than array spreading. Like array spreading, it proceeds from left-to-right, but the result is still an object. This means that properties that come later in the spread object overwrite properties that come earlier. So if we modify the previous example to spread at the end: let defaults = { food: "spicy", price: "$$", ambiance: "noisy" }; let search = { food: "rich", ...defaults }; Then the `food` property in `defaults` overwrites `food: "rich"`, which is not what we want in this case. Object spread also has a couple of other surprising limits. First, it only includes an objects’ [own, enumerable properties](https://developer.mozilla.org/docs/Web/JavaScript/Enumerability_and_ownership_of_properties). Basically, that means you lose methods when you spread instances of an object: class C { p = 12; m() {} } let c = new C(); let clone = { ...c }; clone.p; // ok clone.m(); // error! Second, the TypeScript compiler doesn’t allow spreads of type parameters from generic functions. That feature is expected in future versions of the language. ## `using` declarations `using` declarations are an upcoming feature for JavaScript that are part of the [Stage 3 Explicit Resource Management](https://github.com/tc39/proposal- explicit-resource-management) proposal. A `using` declaration is much like a `const` declaration, except that it couples the _lifetime_ of the value bound to the declaration with the _scope_ of the variable. When control exits the block containing a `using` declaration, the `[Symbol.dispose]()` method of the declared value is executed, which allows that value to perform cleanup: function f() { using x = new C(); doSomethingWith(x); } // `x[Symbol.dispose]()` is called At runtime, this has an effect _roughly_ equivalent to the following: function f() { const x = new C(); try { doSomethingWith(x); } finally { x[Symbol.dispose](); } } `using` declarations are extremely useful for avoiding memory leaks when working with JavaScript objects that hold on to native references like file handles { using file = await openFile(); file.write(text); doSomethingThatMayThrow(); } // `file` is disposed, even if an error is thrown or scoped operations like tracing function f() { using activity = new TraceActivity("f"); // traces entry into function // ... } // traces exit of function Unlike `var`, `let`, and `const`, `using` declarations do not support destructuring. ### `null` and `undefined` It’s important to note that the value can be `null` or `undefined`, in which case nothing is disposed at the end of the block: { using x = b ? new C() : null; // ... } which is _roughly_ equivalent to: { const x = b ? new C() : null; try { // ... } finally { x?.[Symbol.dispose](); } } This allows you to conditionally acquire resources when declaring a `using` declaration without the need for complex branching or repetition. ### Defining a disposable resource You can indicate the classes or objects you produce are disposable by implementing the `Disposable` interface: // from the default lib: interface Disposable { [Symbol.dispose](): void; } // usage: class TraceActivity implements Disposable { readonly name: string; constructor(name: string) { this.name = name; console.log(`Entering: ${name}`); } [Symbol.dispose](): void { console.log(`Exiting: ${name}`); } } function f() { using _activity = new TraceActivity("f"); console.log("Hello world!"); } f(); // prints: // Entering: f // Hello world! // Exiting: f ## `await using` declarations Some resources or operations may have cleanup that needs to be performed asynchronously. To accommodate this, the [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management) proposal also introduces the `await using` declaration: async function f() { await using x = new C(); } // `await x[Symbol.asyncDispose]()` is invoked An `await using` declaration invokes, and _awaits_ , its value’s `[Symbol.asyncDispose]()` method as control leaves the containing block. This allows for asynchronous cleanup, such as a database transaction performing a rollback or commit, or a file stream flushing any pending writes to storage before it is closed. As with `await`, `await using` can only be used in an `async` function or method, or at the top level of a module. ### Defining an asynchronously disposable resource Just as `using` relies on objects that are `Disposable`, an `await using` relies on objects that are `AsyncDisposable`: // from the default lib: interface AsyncDisposable { [Symbol.asyncDispose]: PromiseLike; } // usage: class DatabaseTransaction implements AsyncDisposable { public success = false; private db: Database | undefined; private constructor(db: Database) { this.db = db; } static async create(db: Database) { await db.execAsync("BEGIN TRANSACTION"); return new DatabaseTransaction(db); } async [Symbol.asyncDispose]() { if (this.db) { const db = this.db: this.db = undefined; if (this.success) { await db.execAsync("COMMIT TRANSACTION"); } else { await db.execAsync("ROLLBACK TRANSACTION"); } } } } async function transfer(db: Database, account1: Account, account2: Account, amount: number) { using tx = await DatabaseTransaction.create(db); if (await debitAccount(db, account1, amount)) { await creditAccount(db, account2, amount); } // if an exception is thrown before this line, the transaction will roll back tx.success = true; // now the transaction will commit } ### `await using` vs `await` The `await` keyword that is part of the `await using` declaration only indicates that the _disposal_ of the resource is `await`-ed. It does _not_ `await` the value itself: { await using x = getResourceSynchronously(); } // performs `await x[Symbol.asyncDispose]()` { await using y = await getResourceAsynchronously(); } // performs `await y[Symbol.asyncDispose]()` ### `await using` and `return` It’s important to note that there is a small caveat with this behavior if you are using an `await using` declaration in an `async` function that returns a `Promise` without first `await`-ing it: function g() { return Promise.reject("error!"); } async function f() { await using x = new C(); return g(); // missing an `await` } Because the returned promise isn’t `await`-ed, it’s possible that the JavaScript runtime may report an unhandled rejection since execution pauses while `await`-ing the asynchronous disposal of `x`, without having subscribed to the returned promise. This is not a problem that is unique to `await using`, however, as this can also occur in an `async` function that uses `try..finally`: async function f() { try { return g(); // also reports an unhandled rejection } finally { await somethingElse(); } } To avoid this situation, it is recommended that you `await` your return value if it may be a `Promise`: async function f() { await using x = new C(); return await g(); } ## `using` and `await using` in `for` and `for..of` statements Both `using` and `await using` can be used in a `for` statement: for (using x = getReader(); !x.eof; x.next()) { // ... } In this case, the lifetime of `x` is scoped to the entire `for` statement and is only disposed when control leaves the loop due to `break`, `return`, `throw`, or when the loop condition is false. In addition to `for` statements, both declarations can also be used in `for..of` statements: function * g() { yield createResource1(); yield createResource2(); } for (using x of g()) { // ... } Here, `x` is disposed at the end of _each iteration of the loop_ , and is then reinitialized with the next value. This is especially useful when consuming resources produced one at a time by a generator. ## `using` and `await using` in older runtimes `using` and `await using` declarations can be used when targeting older ECMAScript editions as long as you are using a compatible polyfill for `Symbol.dispose`/`Symbol.asyncDispose`, such as the one provided by default in recent editions of NodeJS. ##### On this page * var declarations * Scoping rules * Variable capturing quirks * let declarations * Block-scoping * Re-declarations and Shadowing * Block-scoped variable capturing * const declarations * let vs. const * Destructuring * Array destructuring * Tuple destructuring * Object destructuring * Function declarations * Spread * using declarations * null and undefined * Defining a disposable resource * await using declarations * Defining an asynchronously disposable resource * await using vs await * await using and return * using and await using in for and for..of statements * using and await using in older runtimes ##### Is this page helpful? Yes No The TypeScript docs are an open source project. Help us improve these pages [by sending a Pull Request](https://github.com/microsoft/TypeScript- Website/blob/v2/packages/documentation/copy/en/reference/Variable%20Declarations.md) ❤ Contributors to this page: DR OT NS VR BC 24+ Last updated: Mar 11, 2025 # TypeScript Documentation ## Get Started Quick introductions based on your background or preference. * [TS for the New Programmer](docs/handbook/typescript-from-scratch) * [TypeScript for JS Programmers](docs/handbook/typescript-in-5-minutes) * [TS for Java/C# Programmers](docs/handbook/typescript-in-5-minutes-oop) * [TS for Functional Programmers](docs/handbook/typescript-in-5-minutes-func) * [TypeScript Tooling in 5 minutes](docs/handbook/typescript-tooling-in-5-minutes) ## Handbook A great first read for your daily TS work. * [The TypeScript Handbook](docs/handbook/intro) * [The Basics](docs/handbook/2/basic-types) * [Everyday Types](docs/handbook/2/everyday-types) * [Narrowing](docs/handbook/2/narrowing) * [More on Functions](docs/handbook/2/functions) * [Object Types](docs/handbook/2/objects) * Type Manipulation * * [Creating Types from Types](docs/handbook/2/types-from-types) * [Generics](docs/handbook/2/generics) * [Keyof Type Operator](docs/handbook/2/keyof-types) * [Typeof Type Operator](docs/handbook/2/typeof-types) * [Indexed Access Types](docs/handbook/2/indexed-access-types) * [Conditional Types](docs/handbook/2/conditional-types) * [Mapped Types](docs/handbook/2/mapped-types) * [Template Literal Types](docs/handbook/2/template-literal-types) * [Classes](docs/handbook/2/classes) * [Modules](docs/handbook/2/modules) ## Reference Deep dive reference materials. * [Utility Types](docs/handbook/utility-types) * [Cheat Sheets](https://www.typescriptlang.org/cheatsheets/) * [Decorators](docs/handbook/decorators) * [Declaration Merging](docs/handbook/declaration-merging) * [Enums](docs/handbook/enums) * [Iterators and Generators](docs/handbook/iterators-and-generators) * [JSX](docs/handbook/jsx) * [Mixins](docs/handbook/mixins) * [Namespaces](docs/handbook/namespaces) * [Namespaces and Modules](docs/handbook/namespaces-and-modules) * [Symbols](docs/handbook/symbols) * [Triple-Slash Directives](docs/handbook/triple-slash-directives) * [Type Compatibility](docs/handbook/type-compatibility) * [Type Inference](docs/handbook/type-inference) * [Variable Declaration](docs/handbook/variable-declarations) ## Modules Reference How TypeScript models JavaScript modules. * [Introduction](docs/handbook/modules/introduction) * [Theory](docs/handbook/modules/theory) * Guides * * [Choosing Compiler Options](docs/handbook/modules/guides/choosing-compiler-options) * [Reference](docs/handbook/modules/reference) * Appendices * * [ESM/CJS Interoperability](docs/handbook/modules/appendices/esm-cjs-interop) ## Tutorials Using TypeScript in several environments. * [ASP.NET Core](docs/handbook/asp-net-core) * [Gulp](docs/handbook/gulp) * [DOM Manipulation](docs/handbook/dom-manipulation) * [Migrating from JavaScript](docs/handbook/migrating-from-javascript) * [Using Babel with TypeScript](docs/handbook/babel-with-typescript) ## Declaration Files Learn how to write declaration files to describe existing JavaScript. Important for DefinitelyTyped contributions. * [Introduction](docs/handbook/declaration-files/introduction) * [Declaration Reference](docs/handbook/declaration-files/by-example) * [Library Structures](docs/handbook/declaration-files/library-structures) * .d.ts Templates * * [Modules .d.ts](docs/handbook/declaration-files/templates/module-d-ts) * [Module: Plugin](docs/handbook/declaration-files/templates/module-plugin-d-ts) * [Module: Class](docs/handbook/declaration-files/templates/module-class-d-ts) * [Module: Function](docs/handbook/declaration-files/templates/module-function-d-ts) * [Global .d.ts](docs/handbook/declaration-files/templates/global-d-ts) * [Global: Modifying Module](docs/handbook/declaration-files/templates/global-modifying-module-d-ts) * [Do's and Don'ts](docs/handbook/declaration-files/do-s-and-don-ts) * [Deep Dive](docs/handbook/declaration-files/deep-dive) * [Publishing](docs/handbook/declaration-files/publishing) * [Consumption](docs/handbook/declaration-files/consumption) ## JavaScript How to use TypeScript-powered JavaScript tooling. * [JS Projects Utilizing TypeScript](docs/handbook/intro-to-js-ts) * [Type Checking JavaScript Files](docs/handbook/type-checking-javascript-files) * [JSDoc Reference](docs/handbook/jsdoc-supported-types) * [Creating .d.ts Files from .js files](docs/handbook/declaration-files/dts-from-js) ## Project Configuration Compiler configuration reference. * [What is a tsconfig.json](docs/handbook/tsconfig-json) * [Compiler Options in MSBuild](docs/handbook/compiler-options-in-msbuild) * [TSConfig Reference](tsconfig/index) * [tsc CLI Options](docs/handbook/compiler-options) * [Project References](docs/handbook/project-references) * [Integrating with Build Tools](docs/handbook/integrating-with-build-tools) * [Configuring Watch](docs/handbook/configuring-watch) * [Nightly Builds](docs/handbook/nightly-builds) ## Cheat Sheets Downloadable syntax reference pages for different parts of everyday TypeScript code. * [Control Flow Analysis](https://www.typescriptlang.org/static/TypeScript%20Control%20Flow%20Analysis-8a549253ad8470850b77c4c5c351d457.png) * [Classes](https://www.typescriptlang.org/static/TypeScript%20Classes-83cc6f8e42ba2002d5e2c04221fa78f9.png) * [Interfaces](https://www.typescriptlang.org/static/TypeScript%20Interfaces-34f1ad12132fb463bd1dfe5b85c5b2e6.png) * [Types](https://www.typescriptlang.org/static/TypeScript%20Types-ae199d69aeecf7d4a2704a528d0fd3f9.png) * [Download PDFs and PNGs](https://www.typescriptlang.org/assets/typescript-cheat-sheets.zip) ## Learning Resources ## Get Started * [JS to TS](docs/handbook/typescript-in-5-minutes) * [New to Programming](docs/handbook/typescript-from-scratch) * [OOP to JS](docs/handbook/typescript-in-5-minutes-oop) * [Functional to JS](docs/handbook/typescript-in-5-minutes-func) * [Installation](https://www.typescriptlang.org/download/) ## Handbook * [Everyday Types](docs/handbook/2/everyday-types) * [Creating Types from Types](docs/handbook/2/types-from-types) * [Object Types](docs/handbook/2/objects) * [Variable Declarations](docs/handbook/variable-declarations) * [More on Functions](docs/handbook/2/functions) ## Tools * [Playground](https://www.typescriptlang.org/play/) * [TSConfig Reference](tsconfig/index) ## Release Notes * [What's new in 5.8](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html) ## Tutorials * [ASP.NET](docs/handbook/asp-net-core) * [Migrating from JS](docs/handbook/migrating-from-javascript) * [Working with the DOM](docs/handbook/dom-manipulation) * [React & Webpack](https://www.typescriptlang.org/docs/handbook/react-&-webpack.html) # TSConfig Reference Intro to the TSConfig Reference A TSConfig file in a directory indicates that the directory is the root of a TypeScript or JavaScript project... ## Compiler Options ##### Top Level 1. `files, ` 2. `extends, ` 3. `include, ` 4. `exclude and ` 5. `references` #### `"compilerOptions"` ##### Type Checking 1. `allowUnreachableCode, ` 2. `allowUnusedLabels, ` 3. `alwaysStrict, ` 4. `exactOptionalPropertyTypes, ` 5. `noFallthroughCasesInSwitch, ` 6. `noImplicitAny, ` 7. `noImplicitOverride, ` 8. `noImplicitReturns, ` 9. `noImplicitThis, ` 10. `noPropertyAccessFromIndexSignature, ` 11. `noUncheckedIndexedAccess, ` 12. `noUnusedLocals, ` 13. `noUnusedParameters, ` 14. `strict, ` 15. `strictBindCallApply, ` 16. `strictBuiltinIteratorReturn, ` 17. `strictFunctionTypes, ` 18. `strictNullChecks, ` 19. `strictPropertyInitialization and ` 20. `useUnknownInCatchVariables` ##### Modules 1. `allowArbitraryExtensions, ` 2. `allowImportingTsExtensions, ` 3. `allowUmdGlobalAccess, ` 4. `baseUrl, ` 5. `customConditions, ` 6. `module, ` 7. `moduleResolution, ` 8. `moduleSuffixes, ` 9. `noResolve, ` 10. `noUncheckedSideEffectImports, ` 11. `paths, ` 12. `resolveJsonModule, ` 13. `resolvePackageJsonExports, ` 14. `resolvePackageJsonImports, ` 15. `rewriteRelativeImportExtensions, ` 16. `rootDir, ` 17. `rootDirs, ` 18. `typeRoots and ` 19. `types` ##### Emit 1. `declaration, ` 2. `declarationDir, ` 3. `declarationMap, ` 4. `downlevelIteration, ` 5. `emitBOM, ` 6. `emitDeclarationOnly, ` 7. `importHelpers, ` 8. `inlineSourceMap, ` 9. `inlineSources, ` 10. `mapRoot, ` 11. `newLine, ` 12. `noEmit, ` 13. `noEmitHelpers, ` 14. `noEmitOnError, ` 15. `outDir, ` 16. `outFile, ` 17. `preserveConstEnums, ` 18. `removeComments, ` 19. `sourceMap, ` 20. `sourceRoot and ` 21. `stripInternal` ##### JavaScript Support 1. `allowJs, ` 2. `checkJs and ` 3. `maxNodeModuleJsDepth` ##### Editor Support 1. `disableSizeLimit and ` 2. `plugins` ##### Interop Constraints 1. `allowSyntheticDefaultImports, ` 2. `erasableSyntaxOnly, ` 3. `esModuleInterop, ` 4. `forceConsistentCasingInFileNames, ` 5. `isolatedDeclarations, ` 6. `isolatedModules, ` 7. `preserveSymlinks and ` 8. `verbatimModuleSyntax` ##### Backwards Compatibility 1. `charset, ` 2. `importsNotUsedAsValues, ` 3. `keyofStringsOnly, ` 4. `noImplicitUseStrict, ` 5. `noStrictGenericChecks, ` 6. `out, ` 7. `preserveValueImports, ` 8. `suppressExcessPropertyErrors and ` 9. `suppressImplicitAnyIndexErrors` ##### Language and Environment 1. `emitDecoratorMetadata, ` 2. `experimentalDecorators, ` 3. `jsx, ` 4. `jsxFactory, ` 5. `jsxFragmentFactory, ` 6. `jsxImportSource, ` 7. `lib, ` 8. `libReplacement, ` 9. `moduleDetection, ` 10. `noLib, ` 11. `reactNamespace, ` 12. `target and ` 13. `useDefineForClassFields` ##### Compiler Diagnostics 1. `diagnostics, ` 2. `explainFiles, ` 3. `extendedDiagnostics, ` 4. `generateCpuProfile, ` 5. `generateTrace, ` 6. `listEmittedFiles, ` 7. `listFiles, ` 8. `noCheck and ` 9. `traceResolution` ##### Projects 1. `composite, ` 2. `disableReferencedProjectLoad, ` 3. `disableSolutionSearching, ` 4. `disableSourceOfProjectReferenceRedirect, ` 5. `incremental and ` 6. `tsBuildInfoFile` ##### Output Formatting 1. `noErrorTruncation, ` 2. `preserveWatchOutput and ` 3. `pretty` ##### Completeness 1. `skipDefaultLibCheck and ` 2. `skipLibCheck` ##### Command Line ##### Watch Options 1. `assumeChangesOnlyAffectDirectDependencies` #### `"watchOptions"` ##### watchOptions 1. `watchFile, ` 2. `watchDirectory, ` 3. `fallbackPolling, ` 4. `synchronousWatchDirectory, ` 5. `excludeDirectories and ` 6. `excludeFiles` #### `"typeAcquisition"` ##### typeAcquisition 1. `enable, ` 2. `include, ` 3. `exclude and ` 4. `disableFilenameBasedTypeAcquisition` ### 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. { "compilerOptions": {}, "files": [ "core.ts", "sys.ts", "types.ts", "scanner.ts", "parser.ts", "utilities.ts", "binder.ts", "checker.ts", "tsc.ts" ] } This is useful when you only have a small number of files and don’t need to use a glob to reference many files. If you need that then use `include`. * Default: `false` * Related: * `include` * `exclude` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### Extends - `extends` The value of `extends` is a string which contains a path to another configuration file to inherit from. The path may use Node.js style resolution. The configuration from the base file are loaded first, then overridden by those in the inheriting config file. All relative paths found in the configuration file will be resolved relative to the configuration file they originated in. It’s worth noting that `files`, `include`, and `exclude` from the inheriting config file _overwrite_ those from the base config file, and that circularity between configuration files is not allowed. Currently, the only top-level property that is excluded from inheritance is `references`. ##### Example `configs/base.json`: { "compilerOptions": { "noImplicitAny": true, "strictNullChecks": true } } `tsconfig.json`: { "extends": "./configs/base", "files": ["main.ts", "supplemental.ts"] } `tsconfig.nostrictnull.json`: { "extends": "./tsconfig", "compilerOptions": { "strictNullChecks": false } } Properties with relative paths found in the configuration file, which aren’t excluded from inheritance, will be resolved relative to the configuration file they originated in. * Default: `false` * Released: [2.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-1.html) ### 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. { "include": ["src/**/*", "tests/**/*"] } Which would include: . ├── scripts ⨯ │ ├── lint.ts ⨯ │ ├── update_deps.ts ⨯ │ └── utils.ts ⨯ ├── src ✓ │ ├── client ✓ │ │ ├── index.ts ✓ │ │ └── utils.ts ✓ │ ├── server ✓ │ │ └── index.ts ✓ ├── tests ✓ │ ├── app.test.ts ✓ │ ├── utils.ts ✓ │ └── tests.d.ts ✓ ├── package.json ├── tsconfig.json └── yarn.lock `include` and `exclude` support wildcard characters to make glob patterns: * `*` matches zero or more characters (excluding directory separators) * `?` matches any one character (excluding directory separators) * `**/` matches any directory nested to any level If 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` if `allowJs` is set to true). * Default: `[]` if `files` is specified; `**/*` otherwise. * Related: * `files` * `exclude` * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### Exclude - `exclude` Specifies an array of filenames or patterns that should be skipped when resolving `include`. **Important** : `exclude` _only_ changes which files are included as a result of the `include` setting. A file specified by `exclude` can still become part of your codebase due to an `import` statement in your code, a `types` inclusion, a `/// 5) { return true; } else { return false; } return true; } With `"allowUnreachableCode": false`: function fn(n: number) { if (n > 5) { return true; } else { return false; } return true; } This does not affect errors on the basis of code which _appears_ to be unreachable due to type analysis. * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### 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: function verifyAge(age: number) { // Forgot 'return' statement if (age > 18) { verified: true; } } * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### Always Strict - `alwaysStrict` Ensures that your files are parsed in the ECMAScript strict mode, and emit “use strict” for each source file. [ECMAScript strict](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Strict_mode) 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` if `strict`; `false` otherwise. * Related: * `strict` * Released: [2.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-1.html) ### Exact Optional Property Types - `exactOptionalPropertyTypes` With exactOptionalPropertyTypes enabled, TypeScript applies stricter rules around how it handles properties on `type` or `interfaces` 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. interface 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” and `undefined`. 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 as `colorThemeOverride` not being defined. For example, `"colorThemeOverride" in settings` would have different behavior with `undefined` as the key compared to not being defined. `exactOptionalPropertyTypes` makes TypeScript truly enforce the definition provided as an optional property: const settings = getUserSettings(); settings.colorThemeOverride = "dark"; settings.colorThemeOverride = "light";   // But not: settings.colorThemeOverride = undefined; * Recommended * Released: [4.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-4.html) ### 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`, or `throw`. This means you won’t accidentally ship a case fallthrough bug. const a: number = 6;   switch (a) { case 0: console.log("even"); case 1: console.log("odd"); break; } * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### 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: function fn(s) { // No error? console.log(s.subtr(3)); } fn(42); Turning on `noImplicitAny` however TypeScript will issue an error whenever it would have inferred `any`: function fn(s) { console.log(s.subtr(3)); } * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### 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: class Album { download() { // Default behavior } }   class SharedAlbum extends Album { 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: class Album { setup() { // Default behavior } }   class MLAlbum extends Album { setup() { // Override to get info from algorithm } }   class SharedAlbum extends Album { download() { // Override to get info from many sources } } In this case, TypeScript has provided no warning that `download` on `SharedAlbum` _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 keyword `override`. The following example has `noImplicitOverride` enabled, and you can see the error received when `override` is missing: class Album { setup() {} }   class MLAlbum extends Album { override setup() {} }   class SharedAlbum extends Album { setup() {} } * Released: [4.3](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-3.html) ### No Implicit Returns - `noImplicitReturns` When enabled, TypeScript will check all code paths in a function to ensure they return a value. function lookupHeadphonesManufacturer(color: "blue" | "black"): string { if (color === "blue") { return "beats"; } else { ("bose"); } } * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### 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` and `this.height` – but the context for `this` inside the function inside `getAreaFunction` is not the instance of the Rectangle. class Rectangle { width: number; height: number;   constructor(width: number, height: number) { this.width = width; this.height = height; }   getAreaFunction() { return function () { return this.width * this.height; }; } } * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### 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: interface GameSettings { // Known up-front properties speed: "fast" | "medium" | "slow"; quality: "high" | "low";   // Assume anything unknown to the interface // is a string. [key: string]: string; }   const settings = getSettings(); settings.speed; settings.quality;   // Unknown key accessors are allowed on // this object, and are `string` settings.username; Turning the flag on will raise an error because the unknown field uses dot syntax instead of indexed syntax. const settings = getSettings(); settings.speed; settings.quality;   // This would need to be settings["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: [4.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-2.html) ### 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. interface EnvironmentVars { NAME: string; OS: string;   // Unknown properties are covered by this index signature. [propName: string]: string; }   declare const env: EnvironmentVars;   // Declared as existing const sysName = env.NAME; const os = env.OS;   // Not declared, but because of the index // signature, then it is considered a string const nodeEnv = env.NODE_ENV; Turning on `noUncheckedIndexedAccess` will add `undefined` to any un-declared field in the type. declare const env: EnvironmentVars;   // Declared as existing const sysName = env.NAME; const os = env.OS;   // Not declared, but because of the index // signature, then it is considered a string const nodeEnv = env.NODE_ENV; * Released: [4.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-1.html) ### No Unused Locals - `noUnusedLocals` Report errors on unused local variables. const createKeyboard = (modelID: number) => { const defaultModelID = 23; return { type: "keyboard", modelID }; }; * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### No Unused Parameters - `noUnusedParameters` Report errors on unused parameters in functions. const createDefaultKeyboard = (modelID: number) => { const defaultModelID = 23; return { type: "keyboard", modelID: defaultModelID }; }; * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### 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: * `alwaysStrict` * `strictNullChecks` * `strictBindCallApply` * `strictBuiltinIteratorReturn` * `strictFunctionTypes` * `strictPropertyInitialization` * `noImplicitAny` * `noImplicitThis` * `useUnknownInCatchVariables` * Released: [2.3](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-3.html) ### Strict Bind Call Apply - `strictBindCallApply` When set, TypeScript will check that the built-in methods of functions `call`, `bind`, and `apply` are invoked with correct argument for the underlying function: // With strictBindCallApply on function fn(x: string) { return parseInt(x); }   const n1 = fn.call(undefined, "10");   const n2 = fn.call(undefined, false); Otherwise, these functions accept any arguments and will return `any`: // With strictBindCallApply off function fn(x: string) { return parseInt(x); }   // Note: No error; return type is 'any' const n = fn.call(undefined, false); * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [3.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-2.html) ### strictBuiltinIteratorReturn - `strictBuiltinIteratorReturn` Built-in iterators are instantiated with a `TReturn` type of undefined instead of `any`. * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [5.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-6.html) ### Strict Function Types - `strictFunctionTypes` When enabled, this flag causes functions parameters to be checked more correctly. Here’s a basic example with `strictFunctionTypes` off: function fn(x: string) { console.log("Hello, " + x.toLowerCase()); }   type StringOrNumberFunc = (ns: string | number) => void;   // Unsafe assignment let func: StringOrNumberFunc = fn; // Unsafe call - will crash func(10); With `strictFunctionTypes` _on_ , the error is correctly detected: function fn(x: string) { console.log("Hello, " + x.toLowerCase()); }   type StringOrNumberFunc = (ns: string | number) => void;   // Unsafe assignment is prevented let 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: type Methodish = { func(x: string | number): void; };   function fn(x: string) { console.log("Hello, " + x.toLowerCase()); }   // Ultimately an unsafe assignment, but not detected const m: Methodish = { func: fn, }; m.func(10); * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [2.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-6.html) ### Strict Null Checks - `strictNullChecks` When `strictNullChecks` is `false`, `null` and `undefined` are effectively ignored by the language. This can lead to unexpected errors at runtime. When `strictNullChecks` is `true`, `null` and `undefined` 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: declare const loggedInUsername: string;   const users = [ { name: "Oby", age: 12 }, { name: "Heera", age: 32 }, ];   const loggedInUser = users.find((u) => u.name === loggedInUsername); console.log(loggedInUser.age); Setting `strictNullChecks` to `true` will raise an error that you have not made a guarantee that the `loggedInUser` exists before trying to use it. declare const loggedInUsername: string;   const users = [ { name: "Oby", age: 12 }, { name: "Heera", age: 32 }, ];   const loggedInUser = users.find((u) => u.name === loggedInUsername); console.log(loggedInUser.age); The second example failed because the array’s `find` function looks a bit like this simplification: // When strictNullChecks: true type 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 result type Array = { find(predicate: (value: any, index: number) => boolean): S; }; * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### 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. class UserAccount { name: string; accountType = "user";   email: string; 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 potentially `undefined` which means it does not have to be set. * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [2.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-7.html) ### 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` to `unknown`. Allowing for code like: try { // ... } catch (err: unknown) { // We have to verify err is an // error before using it as one. if (err instanceof Error) { 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` if `strict`; `false` otherwise. * Related: * `strict` * Released: [4.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-4.html) ## 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: /* app.css */ .cookie-banner { display: none; } // app.d.css.ts declare const css: { cookieBanner: string; }; export default css; // App.tsx import styles from "./app.css"; styles.cookieBanner; // string By 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 of `app.d.css.ts` \- however, this just worked through Node’s `require` resolution rules for CommonJS. Strictly speaking, the former is interpreted as a declaration file for a JavaScript file named `app.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` or `nodenext`. For more information, read up [the proposal for this feature](https://github.com/microsoft/TypeScript/issues/50133) and [its corresponding pull request](https://github.com/microsoft/TypeScript/pull/51435). * Released: [5.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-0.html) ### Allow Importing TS Extensions - `allowImportingTsExtensions` `--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. * Default: `true` if `rewriteRelativeImportExtensions`; `false` otherwise. * Released: [5.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-0.html) ### Allow Umd Global Access - `allowUmdGlobalAccess` 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: [3.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-5.html) ### 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.json With `"baseUrl": "./"`, TypeScript will look for files starting at the same folder as the `tsconfig.json`: import { 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 using `paths`. * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### Custom Conditions - `customConditions` `--customConditions` takes a list of additional [conditions](https://nodejs.org/api/packages.html#nested-conditions) that should succeed when TypeScript resolves from an [`exports`](https://nodejs.org/api/packages.html#exports) or [`imports`](https://nodejs.org/api/packages.html#imports) field of a `package.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: { "compilerOptions": { "target": "es2022", "moduleResolution": "bundler", "customConditions": ["my-condition"] } } Any time an `exports` or `imports` field is referenced in `package.json`, TypeScript will consider conditions called `my-condition`. So when importing from a package with the following `package.json` { // ... "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`, and `bundler` options for `--moduleResolution`. * Related: * `moduleResolution` * `resolvePackageJsonExports` * `resolvePackageJsonImports` * Released: [5.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-0.html) ### Module - `module` Sets the module system for the program. See the [theory behind TypeScript’s `module` option](docs/handbook/modules/theory#the-module-output-format) and [its reference page](docs/handbook/modules/reference#the-module-compiler- option) for more information. You very likely want `"nodenext"` for modern Node.js projects and `preserve` or `esnext` for code that will be bundled. Changing `module` affects `moduleResolution` which [also has a reference page](docs/handbook/modules/reference#the-moduleresolution-compiler-option). Here’s some example output for this file: // @filename: index.ts import { valueOfPi } from "./constants";   export const twoPi = valueOfPi * 2; #### `CommonJS` "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.twoPi = void 0; const constants_1 = require("./constants"); exports.twoPi = constants_1.valueOfPi * 2;   #### `UMD` (function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "./constants"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.twoPi = void 0; const constants_1 = require("./constants"); exports.twoPi = constants_1.valueOfPi * 2; });   #### `AMD` define(["require", "exports", "./constants"], function (require, exports, constants_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.twoPi = void 0; exports.twoPi = constants_1.valueOfPi * 2; });   #### `System` System.register(["./constants"], function (exports_1, context_1) { "use strict"; var constants_1, twoPi; var __moduleName = context_1 && context_1.id; return { setters: [ function (constants_1_1) { constants_1 = constants_1_1; } ], execute: function () { exports_1("twoPi", twoPi = constants_1.valueOfPi * 2); } }; });   #### `ESNext` import { valueOfPi } from "./constants"; export const twoPi = valueOfPi * 2;   #### `ES2015`/`ES6`/`ES2020`/`ES2022` import { valueOfPi } from "./constants"; export const twoPi = valueOfPi * 2;   In addition to the base functionality of `ES2015`/`ES6`, `ES2020` adds support for [dynamic `import`s](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Operators/import), and [`import.meta`](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Operators/import.meta) while `ES2022` further adds support for [top level `await`](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Operators/await#top_level_await). #### `node16`/`node18`/`nodenext` The `node16`, `node18`, and `nodenext` modes integrate with Node’s [native ECMAScript Module support](https://nodejs.org/api/esm.html). The emitted JavaScript uses either `CommonJS` or `ES2020` output depending on the file extension and the value of the `type` setting in the nearest `package.json`. Module resolution also works differently. You can learn more in the [handbook](docs/handbook/esm-node) and [Modules Reference](docs/handbook/modules/reference#node16-node18-nodenext). * `node16` is available from TypeScript 4.7 * `node18` is available from TypeScript 5.8 as a replacement for `node16`, with added support for import attributes. * `nodenext` is available from TypeScript 4.7, but its behavior changes with the latest stable versions of Node.js. As of TypeScript 5.8, `nodenext` supports `require` of ECMAScript modules. #### `preserve` In `--module preserve` ([added](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-4.html#support-for-require-calls-in---moduleresolution- bundler-and---module-preserve) in TypeScript 5.4), ECMAScript imports and exports written in input files are preserved in the output, and CommonJS-style `import x = require("...")` and `export = ...` statements are emitted as CommonJS `require` and `module.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). import { 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 setting `noEmit`? TypeScript’s type checking and module > resolution behavior are affected by the module format that it _would_ emit. > Setting `module` 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. #### `None` "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` if `target` is `ES5`; `ES6`/`ES2015` otherwise. * Allowed: * `none` * `commonjs` * `amd` * `umd` * `system` * `es6`/`es2015` * `es2020` * `es2022` * `esnext` * `node16` * `node18` * `nodenext` * `preserve` * Related: * `moduleResolution` * `esModuleInterop` * `allowImportingTsExtensions` * `allowArbitraryExtensions` * `resolveJsonModule` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### 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 CommonJS `require`, which resolve using different algorithms. These `moduleResolution` values, when combined with the corresponding `module` values, picks the right algorithm for each resolution based on whether Node.js will see an `import` or `require` in the output JavaScript code. * `'node10'` (previously called `'node'`) for Node.js versions older than v10, which only support CommonJS `require`. You probably won’t need to use `node10` in modern code. * `'bundler'` for use with bundlers. Like `node16` and `nodenext`, 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. There are reference pages explaining the [theory behind TypeScript’s module resolution](docs/handbook/modules/theory#module-resolution) and the [details of each option](docs/handbook/modules/reference#the-moduleresolution-compiler- option). * Default: `Node10` if `module` is `CommonJS`; `Node16` if `module` is `Node16` or `Node18`; `NodeNext` if `module` is `NodeNext`; `Bundler` if `module` is `Preserve`; `Classic` otherwise. * Allowed: * `classic` * `node10`/`node` * `node16` * `nodenext` * `bundler` * Related: * `module` * `paths` * `baseUrl` * `rootDirs` * `moduleSuffixes` * `customConditions` * `resolvePackageJsonExports` * `resolvePackageJsonImports` * Released: [1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html) ### Module Suffixes - `moduleSuffixes` Provides a way to override the default list of file name suffixes to search when resolving a module. { "compilerOptions": { "moduleSuffixes": [".ios", ".native", ""] } } Given the above configuration, an import like the following: import * 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 `""` in `moduleSuffixes` 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: [4.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-7.html) ### No Resolve - `noResolve` By default, TypeScript will examine the initial set of files for `import` and `= 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](https://www.npmjs.com/package/tslib) via `importHelpers` to reduce the amount of inline JavaScript too: "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 if `Symbol.iterator` is not present in the runtime. #### Example: Effects on Array Spreads This is an array spread: // Make a new array whose elements are 1 followed by the elements of arr2 const arr = [1, ...arr2]; Based on the description, it sounds easy to downlevel to ES5: // The same, right? const arr = [1].concat(arr2); However, this is observably different in certain rare cases. For example, if 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. // Make an array where the element at index 1 is missing let 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 use `Symbol.iterator` (if present) to more accurately emulate ES 6 behavior. * Related: * `importHelpers` * Released: [2.3](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-3.html) ### Emit BOM - `emitBOM` Controls whether TypeScript will emit a [byte order mark (BOM)](https://wikipedia.org/wiki/Byte_order_mark) 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. * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Emit Declaration Only - `emitDeclarationOnly` _Only_ emit `.d.ts` files; do not emit `.js` files. 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: * `declaration` * Released: [2.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-8.html) ### 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](https://www.npmjs.com/package/tslib) module. You will need to ensure that the `tslib` module is able to be imported at runtime. This only affects modules; global script files will not attempt to import modules. For example, with this TypeScript: export function fn(arr: number[]) { const arr2 = [1, ...arr]; } Turning on `downlevelIteration` and `importHelpers` is still false: var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __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` and `importHelpers`: import { __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: * `noEmitHelpers` * `downlevelIteration` * Released: [2.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-1.html) ### 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: const helloWorld = "hi"; console.log(helloWorld); Converts to this JavaScript: "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. "use strict"; const helloWorld = "hi"; console.log(helloWorld); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMifQ== * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### 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’s `sourcesContent` property). This is often useful in the same cases as `inlineSourceMap`. Requires either `sourceMap` or `inlineSourceMap` to be set. For example, with this TypeScript: const helloWorld = "hi"; console.log(helloWorld); By default converts to this JavaScript: "use strict"; const helloWorld = "hi"; console.log(helloWorld);   Then enable building it with `inlineSources` and `inlineSourceMap` 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 in `inlineSourceMap` because the source-map now contains the original source code also. "use strict"; const helloWorld = "hi"; console.log(helloWorld); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBoZWxsb1dvcmxkID0gXCJoaVwiO1xuY29uc29sZS5sb2coaGVsbG9Xb3JsZCk7Il19 * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### 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: { "compilerOptions": { "sourceMap": true, "mapRoot": "https://my-website.com/debug/sourcemaps/" } } Would declare that `index.js` will have sourcemaps at `https://my- website.com/debug/sourcemaps/index.js.map`. * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### New Line - `newLine` Specify the end of line sequence to be used when emitting files: ‘CRLF’ (dos) or ‘LF’ (unix). * Default: `lf` * Allowed: * `crlf` * `lf` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### 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](https://babeljs.io), or [swc](https://github.com/swc-project/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. * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### No Emit Helpers - `noEmitHelpers` 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 a `await`-like function and `generator`-like function to run: const getAPI = async (url: string) => { // Get API return {}; }; Which creates quite a lot of JavaScript: "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 = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["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 API return [2 /*return*/, {}]; }); }); };   Which can be switched out with your own globals via this flag: "use strict"; var getAPI = function (url) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { // Get API return [2 /*return*/, {}]; }); }); };   * Related: * `importHelpers` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### 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: [1.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-4.html) ### Out Dir - `outDir` If specified, `.js` (as well as `.d.ts`, `.js.map`, etc.) files will be emitted into this directory. The directory structure of the original source files is preserved; see `rootDir` if the computed root is not what you intended. If not specified, `.js` files will be emitted in the same directory as the `.ts` files they were generated from: $ tsc example ├── index.js └── index.ts With a `tsconfig.json` like this: { "compilerOptions": { "outDir": "dist" } } Running `tsc` with these settings moves the files into the specified `dist` folder: $ tsc example ├── dist │ └── index.js ├── index.ts └── tsconfig.json * Related: * `out` * `outFile` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Out File - `outFile` If specified, all _global_ (non-module) files will be concatenated into the single output file specified. If `module` is `system` or `amd`, all module files will also be concatenated into this file after all global content. Note: `outFile` cannot be used unless `module` is `None`, `System`, or `AMD`. This option _cannot_ be used to bundle CommonJS or ES6 modules. * Related: * `out` * `outDir` * Released: [1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html) ### 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: const enum Album { JimmyEatWorldFutures = 1, TubRingZooHypothesis = 2, DogFashionDiscoAdultery = 3, }   const selectedAlbum = Album.JimmyEatWorldFutures; if (selectedAlbum === Album.JimmyEatWorldFutures) { console.log("That is a great choice."); } The default `const enum` behavior is to convert any `Album.Something` to the corresponding number literal, and to remove a reference to the enum from the JavaScript completely. "use strict"; const selectedAlbum = 1 /* Album.JimmyEatWorldFutures */; if (selectedAlbum === 1 /* Album.JimmyEatWorldFutures */) { console.log("That is a great choice."); }   With `preserveConstEnums` set to `true`, the `enum` exists at runtime and the numbers are still emitted. "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` if `isolatedModules`; `false` otherwise. * Released: [1.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-4.html) ### Remove Comments - `removeComments` Strips all comments from TypeScript files when converting into JavaScript. Defaults to `false`. For example, this is a TypeScript file which has a JSDoc comment: /** The translation of 'Hello world' into Portuguese */ export const helloWorldPTBR = "Olá Mundo"; When `removeComments` is set to `true`: export const helloWorldPTBR = "Olá Mundo";   Without setting `removeComments` or having it as `false`: /** The translation of 'Hello world' into Portuguese */ export const helloWorldPTBR = "Olá Mundo";   This means that your comments will show up in the JavaScript code. * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Source Map - `sourceMap` Enables the generation of [sourcemap files](https://developer.mozilla.org/docs/Tools/Debugger/How_to/Use_a_source_map). 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: // helloWorld.ts export declare const helloWorld = "hi"; Compiling with `sourceMap` set to `true` creates the following JavaScript file: // helloWorld.js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.helloWorld = "hi"; //# sourceMappingURL=// helloWorld.js.map And this also generates this json map: // helloWorld.js.map { "version": 3, "file": "ex.js", "sourceRoot": "", "sources": ["../ex.ts"], "names": [], "mappings": ";;AAAa,QAAA,UAAU,GAAG,IAAI,CAAA" } * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Source Root - `sourceRoot` 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: { "compilerOptions": { "sourceMap": true, "sourceRoot": "https://my-website.com/debug/source/" } } Would declare that `index.js` will have a source file at `https://my- website.com/debug/source/index.ts`. * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Strip Internal - `stripInternal` 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 your `d.ts` files, look at [api-extractor](https://api-extractor.com). /** * Days available in a week * @internal */ export const daysInAWeek = 7;   /** Calculate how much someone earns in a week */ export function weeklySalary(dayRate: number) { return daysInAWeek * dayRate; } With the flag set to `false` (default): /** * 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 to `true` the `d.ts` emitted will be redacted. /** Calculate how much someone earns in a week */ export declare function weeklySalary(dayRate: number): number;   The JavaScript output is still the same. * Internal * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ## 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: // @filename: card.js export const defaultCardDeck = "Heart"; When imported into a TypeScript file will raise an error: // @filename: index.ts import { defaultCardDeck } from "./card";   console.log(defaultCardDeck); Imports fine with `allowJs` enabled: // @filename: index.ts import { 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` and `emitDeclarationOnly` to [create declarations for JS files](docs/handbook/declaration-files/dts-from- js). * Related: * `checkJs` * `emitDeclarationOnly` * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### Check JS - `checkJs` Works in tandem with `allowJs`. When `checkJs` is enabled then errors are reported in JavaScript files. This is the equivalent of including `// @ts- check` at the top of all JavaScript files which are included in your project. For example, this is incorrect JavaScript according to the `parseFloat` type definition which comes with TypeScript: // parseFloat only takes a string module.exports.pi = parseFloat(3.142); When imported into a TypeScript module: // @filename: constants.js module.exports.pi = parseFloat(3.142);   // @filename: index.ts import { 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. // @filename: constants.js module.exports.pi = parseFloat(3.142);   // @filename: index.ts import { pi } from "./constants"; console.log(pi); * Related: * `allowJs` * `emitDeclarationOnly` * Released: [2.3](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-3.html) ### 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 your `node_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. * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ## Editor Support ### Disable Size Limit - `disableSizeLimit` To avoid a possible memory bloat issues when working with very large JavaScript projects, there is an upper limit to the amount of memory TypeScript will allocate. Turning this flag on will remove the limit. * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### Plugins - `plugins` List of language service plugins to run inside the editor. Language service plugins are a way to provide additional information to a user based on existing TypeScript files. They can enhance existing messages between TypeScript and an editor, or to provide their own error messages. For example: * [ts-sql-plugin](https://github.com/xialvjun/ts-sql-plugin#readme) — Adds SQL linting with a template strings SQL builder. * [typescript-styled-plugin](https://github.com/Microsoft/typescript-styled-plugin) — Provides CSS linting inside template strings . * [typescript-eslint-language-service](https://github.com/Quramy/typescript-eslint-language-service) — Provides eslint error messaging and fix-its inside the compiler’s output. * [ts-graphql-plugin](https://github.com/Quramy/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](https://code.visualstudio.com/api/references/contribution- points#contributes.typescriptServerPlugins), and so you may have some running in your editor without needing to define them in your `tsconfig.json`. * Released: [2.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-2.html) ## Interop Constraints ### Allow Synthetic Default Imports - `allowSyntheticDefaultImports` When set to true, `allowSyntheticDefaultImports` allows you to write an import like: import React from "react"; instead of: import * as React from "react"; When the module **does not** explicitly specify a default export. For example, without `allowSyntheticDefaultImports` as true: // @filename: utilFunctions.js const getStringLength = (str) => str.length;   module.exports = { getStringLength, };   // @filename: index.ts import utils from "./utilFunctions";   const count = 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: // @filename: utilFunctions.js const 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` if `esModuleInterop` is enabled, `module` is `system`, or `moduleResolution` is `bundler`; `false` otherwise. * Related: * `esModuleInterop` * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### Erasable Syntax Only - `erasableSyntaxOnly` Node.js [supports running TypeScript files directly](https://nodejs.org/api/typescript.html#type-stripping) as of v23.6; however, only TypeScript-specific syntax that does not have runtime semantics are supported under this mode. In other words, it must be possible to easily _erase_ any TypeScript-specific syntax from a file, leaving behind a valid JavaScript file. That means the following constructs are not supported: * `enum` declarations * `namespace`s and `module`s with runtime code * parameter properties in classes * Non-ECMAScript `import =` and `export =` assignments // ❌ error: An `import ... = require(...)` alias import foo = require("foo"); // ❌ error: A namespace with runtime code. namespace container { foo.method(); export type Bar = string; } // ❌ error: An `import =` alias import Bar = container.Bar; class Point { // ❌ error: Parameter properties constructor(public x: number, public y: number) {} } // ❌ error: An `export =` assignment. export = Point; // ❌ error: An enum declaration. enum Direction { Up, Down, Left, Right, } Similar tools like [ts-blank-space](https://github.com/bloomberg/ts-blank- space) or [Amaro](https://github.com/nodejs/amaro) (the underlying library for type-stripping in Node.js) have the same limitations. These tools will provide helpful error messages if they encounter code that doesn’t meet these requirements, but you still won’t find out your code doesn’t work until you actually try to run it. The `--erasableSyntaxOnly` flag will cause TypeScript to error on most TypeScript-specific constructs that have runtime behavior. class C { constructor(public x: number) { } // ~~~~~~~~~~~~~~~~ // error! This syntax is not allowed when 'erasableSyntaxOnly' is enabled. } } Typically, you will want to combine this flag with the `--verbatimModuleSyntax`, which ensures that a module contains the appropriate import syntax, and that import elision does not take place. ### 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 as `const moment = require("moment")` * a default import like `import moment from "moment"` acts the same as `const 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: import * as fs from "fs"; import _ from "lodash"; fs.readFileSync("file.txt", "utf8"); _.chunk(["a", "b", "c", "d"], 2); With `esModuleInterop` disabled: "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 to `true`: "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 () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __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](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) (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 disable `esModuleInterop`. _Note_ : You can make JS emit terser by enabling `importHelpers`: "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 enable `allowSyntheticDefaultImports`. * Recommended * Default: `true` if `module` is `node16`, `nodenext`, or `preserve`; `false` otherwise. * Related: * `allowSyntheticDefaultImports` * Released: [2.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-7.html) ### 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` * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### isolatedDeclarations - `isolatedDeclarations` Require sufficient annotation on exports so other tools can trivially generate declaration files. For more information, see the [5.5 release notes](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-5.html#isolated-declarations) * Released: [5.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-5.html) ### 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](https://babeljs.io) 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 and `namespace`s. Setting the `isolatedModules` flag tells TypeScript to warn you if you write certain code that can’t be correctly interpreted by a single-file transpilation process. It does not change the behavior of your code, or otherwise change the behavior of TypeScript’s checking and emitting process. Some examples of code which does not work when `isolatedModules` is enabled. #### Exports of Non-Value Identifiers In TypeScript, you can import a _type_ and then subsequently export it: import { someType, someFunction } from "someModule";   someFunction();   export { someType, someFunction }; Because there’s no value for `someType`, the emitted `export` will not try to export it (this would be a runtime error in JavaScript): export { someFunction }; Single-file transpilers don’t know whether `someType` produces a value or not, so it’s an error to export a name that only refers to a type. #### Non-Module Files If `isolatedModules` is set, namespaces are only allowed in _modules_ (which means it has some form of `import`/`export`). An error occurs if a namespace is found in a non-module file: namespace Instantiated { export const x = 1; } This restriction doesn’t apply to `.d.ts` files. #### References to `const enum` members In TypeScript, when you reference a `const enum` member, the reference is replaced by its actual value in the emitted JavaScript. Changing this TypeScript: declare const enum Numbers { Zero = 0, One = 1, } console.log(Numbers.Zero + Numbers.One); To this JavaScript: "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 no `Numbers` object at runtime). Because of this, when `isolatedModules` is set, it is an error to reference an ambient `const enum` member. * Default: `true` if `verbatimModuleSyntax`; `false` otherwise. * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### Preserve Symlinks - `preserveSymlinks` 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’s `preserveSymlinks` to true parallels setting Webpack’s `resolve.symlinks` to false, and vice-versa). With this enabled, references to modules and packages (e.g. `import`s and `/// ` 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. * Released: [2.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-5.html) ### Verbatim Module Syntax - `verbatimModuleSyntax` By default, TypeScript does something called _import elision_. Basically, if you write something like import { 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: export 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 export { Car } from "./car"; should be preserved or dropped. If `Car` is declared with something like a `class`, then it can be preserved in the resulting JavaScript file. But if `Car` is only declared as a `type` alias or `interface`, then the JavaScript file shouldn’t export `Car` 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 the `type` modifier. // This statement can be dropped entirely in JS output import type * as car from "./car"; // The named import/export 'Car' can be dropped in JS output import { 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 between `type` and plain imports and exports. So TypeScript has the flag `--importsNotUsedAsValues` to make sure you use the `type` 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 a `type` modifier are left around. Anything that uses the `type` modifier is dropped entirely. // 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 `import`s and `export`s won’t be rewritten to `require` 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 uses `require` and `module.exports`, you’ll have to use TypeScript’s module syntax that predates ES2015: Input TypeScript | Output JavaScript ---|--- import foo = require("foo"); | const foo = require("foo"); function foo() {} function bar() {} function baz() {} export = { foo, bar, baz, }; | function 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 in `package.json`](https://nodejs.org/api/packages.html#type) 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](https://github.com/microsoft/TypeScript/pull/52203) and [its proposal issue](https://github.com/microsoft/TypeScript/issues/51479). * Released: [5.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-0.html) ## Backwards Compatibility ### Charset - `charset` 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` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### 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 dropping `import` statements which only reference types. * `preserve`: Preserves all `import` 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 an `import` statement which should never be emitted into JavaScript. * Default: `remove` * Allowed: * `remove` * `preserve` * `error` * Related: * `preserveValueImports` * `verbatimModuleSyntax` * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Keyof Strings Only - `keyofStringsOnly` This flag changes the `keyof` type operator to return `string` instead of `string | 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](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-9.html#support-number-and-symbol-named-properties-with- keyof-and-mapped-types). * Deprecated * Released: [2.9](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-9.html) ### 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. * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### No Strict Generic Checks - `noStrictGenericChecks` TypeScript will unify type parameters when comparing two generic functions. type A = (x: T, y: U) => [T, U]; type B = (x: S, y: S) => [S, S];   function f(a: A, b: B) { b = a; // Ok a = b; // Error } This flag can be used to remove that check. * Released: [2.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-5.html) ### 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: * `outDir` * `outFile` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### 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: import { 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: * `isolatedModules` * `importsNotUsedAsValues` * `verbatimModuleSyntax` * Released: [4.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-5.html) ### Suppress Excess Property Errors - `suppressExcessPropertyErrors` This disables reporting of excess property errors, such as the one shown in the following example: type Point = { x: number; y: number }; const p: Point = { x: 1, y: 3, m: 10 }; This flag was added to help people migrate to the stricter checking of new object literals in [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html#stricter-object-literal-assignment-checks). We don’t recommend using this flag in a modern codebase, you can suppress one- off cases where you need it using `// @ts-ignore`. * Released: [1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html) ### Suppress Implicit Any Index Errors - `suppressImplicitAnyIndexErrors` Turning `suppressImplicitAnyIndexErrors` on suppresses reporting the error about implicit anys when indexing into objects, as shown in the following example: const obj = { x: 10 }; console.log(obj["foo"]); Using `suppressImplicitAnyIndexErrors` is quite a drastic approach. It is recommended to use a `@ts-ignore` comment instead: const obj = { x: 10 }; // @ts-ignore console.log(obj["foo"]); * Related: * `noImplicitAny` * Released: [1.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-4.html) ## Language and Environment ### Emit Decorator Metadata - `emitDecoratorMetadata` Enables experimental support for emitting type metadata for decorators which works with the module [`reflect- metadata`](https://www.npmjs.com/package/reflect-metadata). For example, here is the TypeScript 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(); With `emitDecoratorMetadata` not set to true (default) the emitted JavaScript is: "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: "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: * `experimentalDecorators` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### Experimental Decorators - `experimentalDecorators` Enables [experimental support for decorators](https://github.com/tc39/proposal-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](docs/handbook/decorators). * Related: * `emitDecoratorMetadata` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### JSX - `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: export const HelloWorld = () =>

Hello world

; React: `"react-jsx"`[[1]](https://reactjs.org/blog/2020/09/22/introducing-the- new-jsx-transform.html) import { jsx as _jsx } from "react/jsx-runtime"; export const HelloWorld = () => _jsx("h1", { children: "Hello world" });   React dev transform: `"react- jsxdev"`[[1]](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx- transform.html) import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime"; const _jsxFileName = "/home/runner/work/TypeScript-Website/TypeScript-Website/packages/typescriptlang-org/index.tsx"; export const HelloWorld = () => _jsxDEV("h1", { children: "Hello world" }, void 0, false, { fileName: _jsxFileName, lineNumber: 9, columnNumber: 32 }, this);   Preserve: `"preserve"` import React from 'react'; export const HelloWorld = () =>

Hello world

;   React Native: `"react-native"` import React from 'react'; export const HelloWorld = () =>

Hello world

;   Legacy React runtime: `"react"` import React from 'react'; export const HelloWorld = () => React.createElement("h1", null, "Hello world");   This option can be used on a per-file basis too using an `@jsxRuntime` comment. Always use the classic runtime (`"react"`) for this file: /* @jsxRuntime classic */ export const HelloWorld = () =>

Hello world

; Always use the automatic runtime (`"react-jsx"`) for this file: /* @jsxRuntime automatic */ export const HelloWorld = () =>

Hello world

; * Allowed: * `preserve` * `react` * `react-native` * `react-jsx` * `react-jsxdev` * Related: * `jsxFactory` * `jsxFragmentFactory` * `jsxImportSource` * Released: [1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html) ### 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 using `preact`. For example, this TSX file: import { h } from "preact"; const HelloWorld = () =>
Hello
; With `jsxFactory: "h"` looks like: const 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](https://babeljs.io/docs/en/babel-plugin-transform-react- jsx#custom). /** @jsx h */ import { h } from "preact";   const HelloWorld = () =>
Hello
; 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`. * Default: `React.createElement` * Allowed: * Any identifier or dotted identifier. * Related: * `jsx` * `jsxFragmentFactory` * `jsxImportSource` * Released: [2.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-2.html) ### 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: { "compilerOptions": { "target": "esnext", "module": "commonjs", "jsx": "react", "jsxFactory": "h", "jsxFragmentFactory": "Fragment" } } This TSX file: import { h, Fragment } from "preact"; const HelloWorld = () => ( <>
Hello
); Would look like: const 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](https://babeljs.io/docs/en/babel-plugin-transform- react-jsx#fragments). For example: /** @jsx h */ /** @jsxFrag Fragment */   import { h, Fragment } from "preact";   const HelloWorld = () => ( <>
Hello
); * Default: `React.Fragment` * Related: * `jsx` * `jsxFactory` * `jsxImportSource` * Released: [4.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-0.html) ### JSX Import Source - `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](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx- transform.html) the library supports a new form of JSX transformation via a separate import. For example with this code: import React from "react"; function App() { return

Hello World

; } Using this TSConfig: { "compilerOptions": { "target": "esnext", "module": "commonjs", "jsx": "react-jsx" } } The emitted JavaScript from TypeScript is: "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: { "compilerOptions": { "target": "esnext", "module": "commonjs", "jsx": "react-jsx", "jsxImportSource": "preact", "types": ["preact"] } } Which generates code like: function App() { return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" }); }   Alternatively, you can use a per-file pragma to set this option, for example: /** @jsxImportSource preact */ export function App() { return

Hello World

; } 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. * Default: `react` * Related: * `jsx` * `jsxFactory` * Released: [4.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-1.html) ### Lib - `lib` TypeScript includes a default set of type definitions for built-in JS APIs (like `Math`), as well as type definitions for things found in browser environments (like `document`). TypeScript also includes APIs for newer JS features matching the `target` you specify; for example the definition for `Map` is available if `target` is `ES6` or newer. You may want to change these for a few reasons: * Your program doesn’t run in a browser, so you don’t want the `"dom"` type definitions * Your runtime platform provides certain JavaScript API objects (maybe through polyfills), but doesn’t yet support the full syntax of a given ECMAScript version * You have polyfills or native implementations for some, but not all, of a higher level ECMAScript version In TypeScript 4.5, lib files can be overridden by npm modules, find out more [in the blog](https://devblogs.microsoft.com/typescript/announcing- typescript-4-5-beta/#supporting-lib-from-node_modules). ### High Level libraries Name | Contents ---|--- `ES5` | Core definitions for all ES5 functionality `ES2015` | Additional APIs available in ES2015 (also known as ES6) - `array.find`, `Promise`, `Proxy`, `Symbol`, `Map`, `Set`, `Reflect`, etc. `ES6` | Alias for “ES2015” `ES2016` | Additional APIs available in ES2016 - `array.include`, etc. `ES7` | Alias for “ES2016” `ES2017` | Additional APIs available in ES2017 - `Object.entries`, `Object.values`, `Atomics`, `SharedArrayBuffer`, `date.formatToParts`, typed arrays, etc. `ES2018` | Additional APIs available in ES2018 - `async` iterables, `promise.finally`, `Intl.PluralRules`, `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. `ES2023` | Additional APIs available in ES2023 - `array.with`, `array.findLast`, `array.findLastIndex`, `array.toSorted`, `array.toReversed`, etc. `ESNext` | Additional APIs available in ESNext - This changes as the JavaScript specification evolves `DOM` | [DOM](https://developer.mozilla.org/docs/Glossary/DOM) definitions - `window`, `document`, etc. `WebWorker` | APIs available in [WebWorker](https://developer.mozilla.org/docs/Web/API/Web_Workers_API/Using_web_workers) contexts `ScriptHost` | APIs for the [Windows Script Hosting System](https://wikipedia.org/wiki/Windows_Script_Host) ### 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](https://github.com/microsoft/TypeScript/tree/main/src/lib). * Related: * `noLib` * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### Lib Replacement - `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](https://www.npmjs.com/package/@types/web?activeTab=readme) with the following `package.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`. * Default: `true` ### Module Detection - `moduleDetection` This setting controls how TypeScript determines whether a file is a [script or a module](docs/handbook/modules/theory#scripts-and-modules-in-javascript). 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. * Default: "auto": Treat files with imports, exports, import.meta, jsx (with jsx: react- jsx), or esm format (with module: node16+) as modules. * Allowed: * `legacy` * `auto` * `force` * Released: [4.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-7.html) ### 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`, and `String`. It is expected that if you use `noLib` you will be including your own type definitions for these. * Related: * `lib` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### React Namespace - `reactNamespace` Use `jsxFactory` instead. Specify the object invoked for `createElement` when targeting `react` for TSX files. * Default: `React` * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### Target - `target` Modern browsers support all ES6 features, so `ES6` is a good choice. You might choose to set a lower target if your code is deployed to older environments, or a higher target if your code is guaranteed to run in newer environments. The `target` setting changes which JS features are downleveled and which are left intact. For example, an arrow function `() => this` will be turned into an equivalent `function` expression if `target` is ES5 or lower. Changing `target` also changes the default value of `lib`. You may “mix and match” `target` and `lib` settings as desired, but you could just set `target` for convenience. For developer platforms like Node 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](https://github.com/tsconfig/bases#centralized- recommendations-for-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: `ES5` * Allowed: * `es3` * `es5` * `es6`/`es2015` * `es2016` * `es2017` * `es2018` * `es2019` * `es2020` * `es2021` * `es2022` * `es2023` * `es2024` * `esnext` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### 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](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare- property-modifier). * Default: `true` if `target` is `ES2022` or higher, including `ESNext`; `false` otherwise. * Released: [3.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html) ## 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 * Related: * `extendedDiagnostics` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Explain Files - `explainFiles` Print names of files which TypeScript sees as a part of your project and the reason they are part of the compilation. For example, with this project of just a single `index.ts` file example ├── index.ts ├── package.json └── tsconfig.json Using a `tsconfig.json` which has `explainFiles` set to true: { "compilerOptions": { "target": "es5", "module": "commonjs", "explainFiles": true } } Running TypeScript against this folder would have output like this: ❯ tsc node_modules/typescript/lib/lib.d.ts Default library for target 'es5' node_modules/typescript/lib/lib.es5.d.ts Library referenced via 'es5' from file 'node_modules/typescript/lib/lib.d.ts' node_modules/typescript/lib/lib.dom.d.ts Library referenced via 'dom' from file 'node_modules/typescript/lib/lib.d.ts' node_modules/typescript/lib/lib.webworker.importscripts.d.ts Library referenced via 'webworker.importscripts' from file 'node_modules/typescript/lib/lib.d.ts' node_modules/typescript/lib/lib.scripthost.d.ts Library referenced via 'scripthost' from file 'node_modules/typescript/lib/lib.d.ts' index.ts Matched by include pattern '**/*' in 'tsconfig.json' The output above show: * The initial lib.d.ts lookup based on `target`, and the chain of `.d.ts` files which are referenced * The `index.ts` file located via the default pattern of `include` This option is intended for debugging how a file has become a part of your compile. * Released: [4.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-2.html) ### Extended Diagnostics - `extendedDiagnostics` You can use this flag to discover where TypeScript is spending its time when compiling. This is a tool used for understanding the performance characteristics of your codebase overall. You can learn more about how to measure and understand the output in the performance [section of the wiki](https://github.com/microsoft/TypeScript/wiki/Performance). * Related: * `diagnostics` * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### Generate CPU Profile - `generateCpuProfile` This option gives you the chance to have TypeScript emit a v8 CPU profile during the compiler run. The CPU profile can provide insight into why your builds may be slow. This option can only be used from the CLI via: `--generateCpuProfile tsc- output.cpuprofile`. npm run tsc --generateCpuProfile tsc-output.cpuprofile This file can be opened in a chromium based browser like Chrome or Edge Developer in [the CPU profiler](https://developers.google.com/web/tools/chrome-devtools/rendering- tools/js-execution) section. You can learn more about understanding the compilers performance in the [TypeScript wiki section on performance](https://github.com/microsoft/TypeScript/wiki/Performance). * Default: `profile.cpuprofile` * Released: [3.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html) ### generateTrace - `generateTrace` Generates an event trace and a list of types. * Released: [4.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-1.html) ### List Emitted Files - `listEmittedFiles` Print names of generated files part of the compilation to the terminal. This flag is useful in two cases: * You want to transpile TypeScript as a part of a build chain in the terminal where the filenames are processed in the next command. * You are not sure that TypeScript has included a file you expected, as a part of debugging the file inclusion settings. For example: example ├── index.ts ├── package.json └── tsconfig.json With: { "compilerOptions": { "declaration": true, "listEmittedFiles": true } } Would echo paths like: $ npm run tsc path/to/example/index.js path/to/example/index.d.ts Normally, TypeScript would return silently on success. * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### List Files - `listFiles` Print names of files part of the compilation. This is useful when you are not sure that TypeScript has included a file you expected. For example: example ├── index.ts ├── package.json └── tsconfig.json With: { "compilerOptions": { "listFiles": true } } Would echo paths like: $ npm run tsc path/to/example/node_modules/typescript/lib/lib.d.ts path/to/example/node_modules/typescript/lib/lib.es5.d.ts path/to/example/node_modules/typescript/lib/lib.dom.d.ts path/to/example/node_modules/typescript/lib/lib.webworker.importscripts.d.ts path/to/example/node_modules/typescript/lib/lib.scripthost.d.ts path/to/example/index.ts Note if using TypeScript 4.2, prefer `explainFiles` which offers an explanation of why a file was added too. * Related: * `explainFiles` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### noCheck - `noCheck` Disable full type checking (only critical parse and emit errors will be reported). * Released: [5.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-6.html) ### Trace Resolution - `traceResolution` When you are trying to debug why a module isn’t being included. You can set `traceResolution` to `true` to have TypeScript print information about its resolution process for each processed file. * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ## Projects ### Composite - `composite` The `composite` option enforces certain constraints which make it possible for build tools (including TypeScript itself, under `--build` mode) to quickly determine if a project has been built yet. When this setting is on: * The `rootDir` setting, if not explicitly set, defaults to the directory containing the `tsconfig.json` file. * All implementation files must be matched by an `include` pattern or listed in the `files` array. If this constraint is violated, `tsc` will inform you which files weren’t specified. * `declaration` defaults to `true` You can find documentation on TypeScript projects in [the handbook](docs/handbook/project-references). * Related: * `incremental` * `tsBuildInfoFile` * Released: [3.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-0.html) ### Disable Referenced Project Load - `disableReferencedProjectLoad` In multi-project TypeScript programs, TypeScript will load all of the available projects into memory in order to provide accurate results for editor responses which require a full knowledge graph like ‘Find All References’. If your project is large, you can use the flag `disableReferencedProjectLoad` to disable the automatic loading of all projects. Instead, projects are loaded dynamically as you open files through your editor. * Released: [4.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-0.html) ### Disable Solution Searching - `disableSolutionSearching` When working with [composite TypeScript projects](docs/handbook/project- references), this option provides a way to declare that you do not want a project to be included when using features like _find all references_ or _jump to definition_ in an editor. This flag is something you can use to increase responsiveness in large composite projects. * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Disable Source Project Reference Redirect - `disableSourceOfProjectReferenceRedirect` When working with [composite TypeScript projects](docs/handbook/project- references), this option provides a way to go [back to the pre-3.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html#build-free-editing-with-project-references) behavior where d.ts files were used to as the boundaries between modules. In 3.7 the source of truth is now your TypeScript files. * Released: [3.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html) ### Incremental - `incremental` Tells TypeScript to save information about the project graph from the last compilation to files stored on disk. This creates a series of `.tsbuildinfo` files in the same folder as your compilation output. They are not used by your JavaScript at runtime and can be safely deleted. You can read more about the flag in the [3.4 release notes](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-4.html#faster-subsequent-builds-with-the---incremental- flag). To control which folders you want to the files to be built to, use the config option `tsBuildInfoFile`. * Default: `true` if `composite`; `false` otherwise. * Related: * `composite` * `tsBuildInfoFile` * Released: [3.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-4.html) ### TS Build Info File - `tsBuildInfoFile` This setting lets you specify a file for storing incremental compilation information as a part of composite projects which enables faster building of larger TypeScript codebases. You can read more about composite projects [in the handbook](docs/handbook/project-references). The default depends on a combination of other settings: * If `outFile` is set, the default is `.tsbuildinfo`. * If `rootDir` and `outDir` are set, then the file is `//.tsbuildinfo` For example, if `rootDir` is `src`, `outDir` is `dest`, and the config is `./tsconfig.json`, then the default is `./tsconfig.tsbuildinfo` as the relative path from `src/` to `./tsconfig.json` is `../`. * If `outDir` is set, then the default is `/.tsbuildInfo` * Otherwise, the default is `.tsbuildInfo` * Default: `.tsbuildinfo` * Related: * `incremental` * `composite` * Released: [3.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-4.html) ## Output Formatting ### No Error Truncation - `noErrorTruncation` Do not truncate error messages. With `false`, the default. var x: { propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; propertyWithAnExceedinglyLongName8: string; };   // String representation of type of 'x' should be truncated in error message var s: string = x; With `true` var x: { propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; propertyWithAnExceedinglyLongName8: string; };   // String representation of type of 'x' should be truncated in error message var s: string = x; * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Preserve Watch Output - `preserveWatchOutput` Whether to keep outdated console output in watch mode instead of clearing the screen every time a change happened. * Internal * Released: [2.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-8.html) ### Pretty - `pretty` Stylize errors and messages using color and context, this is on by default — offers you a chance to have less terse, single colored messages from the compiler. * Default: `true` * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ## Completeness ### Skip Default Lib Check - `skipDefaultLibCheck` Use `skipLibCheck` instead. Skip type checking of default library declaration files. * Released: [1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html) ### Skip Lib Check - `skipLibCheck` Skip type checking of declaration files. This can save time during compilation at the expense of type-system accuracy. For example, two libraries could define two copies of the same `type` in an inconsistent way. Rather than doing a full check of all `d.ts` files, TypeScript will type check the code you specifically refer to in your app’s source code. A common case where you might think to use `skipLibCheck` is when there are two copies of a library’s types in your `node_modules`. In these cases, you should consider using a feature like [yarn’s resolutions](https://yarnpkg.com/lang/en/docs/selective-version-resolutions/) to ensure there is only one copy of that dependency in your tree or investigate how to ensure there is only one copy by understanding the dependency resolution to fix the issue without additional tooling. Another possibility is when you are migrating between TypeScript releases and the changes cause breakages in node_modules and the JS standard libraries which you do not want to deal with during the TypeScript update. Note, that if these issues come from the TypeScript standard library you can replace the library using [TypeScript 4.5’s lib replacement](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-5.html#supporting-lib-from-node_modules) technique. * Recommended * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ## Command Line ## Watch Options TypeScript 3.8 shipped a new strategy for watching directories, which is crucial for efficiently picking up changes to `node_modules`. On operating systems like Linux, TypeScript installs directory watchers (as opposed to file watchers) on `node_modules` and many of its subdirectories to detect changes in dependencies. This is because the number of available file watchers is often eclipsed by the number of files in `node_modules`, whereas there are way fewer directories to track. Because every project might work better under different strategies, and this new approach might not work well for your workflows, TypeScript 3.8 introduces a new `watchOptions` field which allows users to tell the compiler/language service which watching strategies should be used to keep track of files and directories. ### Assume Changes Only Affect Direct Dependencies - `assumeChangesOnlyAffectDirectDependencies` When this option is enabled, TypeScript will avoid rechecking/rebuilding all truly possibly-affected files, and only recheck/rebuild files that have changed as well as files that directly import them. This can be considered a ‘fast & loose’ implementation of the watching algorithm, which can drastically reduce incremental rebuild times at the expense of having to run the full build occasionally to get all compiler error messages. * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ## Watch Options You can configure the how TypeScript `--watch` works. This section is mainly for handling case where `fs.watch` and `fs.watchFile` have additional constraints like on Linux. You can read more at [Configuring Watch](docs/handbook/configuring-watch). ### Watch File - `watchFile` The strategy for how individual files are watched. * `fixedPollingInterval`: Check every file for changes several times a second at a fixed interval. * `priorityPollingInterval`: Check every file for changes several times a second, but use heuristics to check certain types of files less frequently than others. * `dynamicPriorityPolling`: Use a dynamic queue where less-frequently modified files will be checked less often. * `useFsEvents` (the default): Attempt to use the operating system/file system’s native events for file changes. * `useFsEventsOnParentDirectory`: Attempt to use the operating system/file system’s native events to listen for changes on a file’s parent directory * Allowed: * `fixedpollinginterval` * `prioritypollinginterval` * `dynamicprioritypolling` * `fixedchunksizepolling` * `usefsevents` * `usefseventsonparentdirectory` * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Watch Directory - `watchDirectory` The strategy for how entire directory trees are watched under systems that lack recursive file-watching functionality. * `fixedPollingInterval`: Check every directory for changes several times a second at a fixed interval. * `dynamicPriorityPolling`: Use a dynamic queue where less-frequently modified directories will be checked less often. * `useFsEvents` (the default): Attempt to use the operating system/file system’s native events for directory changes. * Allowed: * `usefsevents` * `fixedpollinginterval` * `dynamicprioritypolling` * `fixedchunksizepolling` * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Fallback Polling - `fallbackPolling` When using file system events, this option specifies the polling strategy that gets used when the system runs out of native file watchers and/or doesn’t support native file watchers. * `fixedPollingInterval`: Check every file for changes several times a second at a fixed interval. * `priorityPollingInterval`: Check every file for changes several times a second, but use heuristics to check certain types of files less frequently than others. * `dynamicPriorityPolling`: Use a dynamic queue where less-frequently modified files will be checked less often. * `synchronousWatchDirectory`: Disable deferred watching on directories. Deferred watching is useful when lots of file changes might occur at once (e.g. a change in `node_modules` from running `npm install`), but you might want to disable it with this flag for some less-common setups. * Allowed: * `fixedinterval` * `priorityinterval` * `dynamicpriority` * `fixedchunksize` * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Synchronous Watch Directory - `synchronousWatchDirectory` Synchronously call callbacks and update the state of directory watchers on platforms that don`t support recursive watching natively. Instead of giving a small timeout to allow for potentially multiple edits to occur on a file. { "watchOptions": { "synchronousWatchDirectory": true } } * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Exclude Directories - `excludeDirectories` You can use `excludeFiles` to drastically reduce the number of files which are watched during `--watch`. This can be a useful way to reduce the number of open file which TypeScript tracks on Linux. { "watchOptions": { "excludeDirectories": ["**/node_modules", "_build", "temp/*"] } } * Released: [4.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-2.html) ### Exclude Files - `excludeFiles` You can use `excludeFiles` to remove a set of specific files from the files which are watched. { "watchOptions": { "excludeFiles": ["temp/file.ts"] } } * Released: [4.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-2.html) ## Type Acquisition Type Acquisition is only important for JavaScript projects. In TypeScript projects you need to include the types in your projects explicitly. However, for JavaScript projects, the TypeScript tooling will download types for your modules in the background and outside of your node_modules folder. ### Enable - `enable` Disables automatic type acquisition in JavaScript projects: { "typeAcquisition": { "enable": false } } ### Include - `include` If you have a JavaScript project where TypeScript needs additional guidance to understand global dependencies, or have disabled the built-in inference via `disableFilenameBasedTypeAcquisition`. You can use `include` to specify which types should be used from DefinitelyTyped: { "typeAcquisition": { "include": ["jquery"] } } ### Exclude - `exclude` Offers a config for disabling the type-acquisition for a certain module in JavaScript projects. This can be useful for projects which include other libraries in testing infrastructure which aren’t needed in the main application. { "typeAcquisition": { "exclude": ["jest", "mocha"] } } ### Disable Filename Based Type Acquisition - `disableFilenameBasedTypeAcquisition` TypeScript’s type acquisition can infer what types should be added based on filenames in a project. This means that having a file like `jquery.js` in your project would automatically download the types for JQuery from DefinitelyTyped. You can disable this via `disableFilenameBasedTypeAcquisition`. { "typeAcquisition": { "disableFilenameBasedTypeAcquisition": true } } * Released: [4.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-1.html) # Intro to the TSConfig Reference Intro to the TSConfig Reference A TSConfig file in a directory indicates that the directory is the root of a TypeScript or JavaScript project... ## Compiler Options ##### Top Level 1. `files, ` 2. `extends, ` 3. `include, ` 4. `exclude and ` 5. `references` #### `"compilerOptions"` ##### Type Checking 1. `allowUnreachableCode, ` 2. `allowUnusedLabels, ` 3. `alwaysStrict, ` 4. `exactOptionalPropertyTypes, ` 5. `noFallthroughCasesInSwitch, ` 6. `noImplicitAny, ` 7. `noImplicitOverride, ` 8. `noImplicitReturns, ` 9. `noImplicitThis, ` 10. `noPropertyAccessFromIndexSignature, ` 11. `noUncheckedIndexedAccess, ` 12. `noUnusedLocals, ` 13. `noUnusedParameters, ` 14. `strict, ` 15. `strictBindCallApply, ` 16. `strictBuiltinIteratorReturn, ` 17. `strictFunctionTypes, ` 18. `strictNullChecks, ` 19. `strictPropertyInitialization and ` 20. `useUnknownInCatchVariables` ##### Modules 1. `allowArbitraryExtensions, ` 2. `allowImportingTsExtensions, ` 3. `allowUmdGlobalAccess, ` 4. `baseUrl, ` 5. `customConditions, ` 6. `module, ` 7. `moduleResolution, ` 8. `moduleSuffixes, ` 9. `noResolve, ` 10. `noUncheckedSideEffectImports, ` 11. `paths, ` 12. `resolveJsonModule, ` 13. `resolvePackageJsonExports, ` 14. `resolvePackageJsonImports, ` 15. `rewriteRelativeImportExtensions, ` 16. `rootDir, ` 17. `rootDirs, ` 18. `typeRoots and ` 19. `types` ##### Emit 1. `declaration, ` 2. `declarationDir, ` 3. `declarationMap, ` 4. `downlevelIteration, ` 5. `emitBOM, ` 6. `emitDeclarationOnly, ` 7. `importHelpers, ` 8. `inlineSourceMap, ` 9. `inlineSources, ` 10. `mapRoot, ` 11. `newLine, ` 12. `noEmit, ` 13. `noEmitHelpers, ` 14. `noEmitOnError, ` 15. `outDir, ` 16. `outFile, ` 17. `preserveConstEnums, ` 18. `removeComments, ` 19. `sourceMap, ` 20. `sourceRoot and ` 21. `stripInternal` ##### JavaScript Support 1. `allowJs, ` 2. `checkJs and ` 3. `maxNodeModuleJsDepth` ##### Editor Support 1. `disableSizeLimit and ` 2. `plugins` ##### Interop Constraints 1. `allowSyntheticDefaultImports, ` 2. `erasableSyntaxOnly, ` 3. `esModuleInterop, ` 4. `forceConsistentCasingInFileNames, ` 5. `isolatedDeclarations, ` 6. `isolatedModules, ` 7. `preserveSymlinks and ` 8. `verbatimModuleSyntax` ##### Backwards Compatibility 1. `charset, ` 2. `importsNotUsedAsValues, ` 3. `keyofStringsOnly, ` 4. `noImplicitUseStrict, ` 5. `noStrictGenericChecks, ` 6. `out, ` 7. `preserveValueImports, ` 8. `suppressExcessPropertyErrors and ` 9. `suppressImplicitAnyIndexErrors` ##### Language and Environment 1. `emitDecoratorMetadata, ` 2. `experimentalDecorators, ` 3. `jsx, ` 4. `jsxFactory, ` 5. `jsxFragmentFactory, ` 6. `jsxImportSource, ` 7. `lib, ` 8. `libReplacement, ` 9. `moduleDetection, ` 10. `noLib, ` 11. `reactNamespace, ` 12. `target and ` 13. `useDefineForClassFields` ##### Compiler Diagnostics 1. `diagnostics, ` 2. `explainFiles, ` 3. `extendedDiagnostics, ` 4. `generateCpuProfile, ` 5. `generateTrace, ` 6. `listEmittedFiles, ` 7. `listFiles, ` 8. `noCheck and ` 9. `traceResolution` ##### Projects 1. `composite, ` 2. `disableReferencedProjectLoad, ` 3. `disableSolutionSearching, ` 4. `disableSourceOfProjectReferenceRedirect, ` 5. `incremental and ` 6. `tsBuildInfoFile` ##### Output Formatting 1. `noErrorTruncation, ` 2. `preserveWatchOutput and ` 3. `pretty` ##### Completeness 1. `skipDefaultLibCheck and ` 2. `skipLibCheck` ##### Command Line ##### Watch Options 1. `assumeChangesOnlyAffectDirectDependencies` #### `"watchOptions"` ##### watchOptions 1. `watchFile, ` 2. `watchDirectory, ` 3. `fallbackPolling, ` 4. `synchronousWatchDirectory, ` 5. `excludeDirectories and ` 6. `excludeFiles` #### `"typeAcquisition"` ##### typeAcquisition 1. `enable, ` 2. `include, ` 3. `exclude and ` 4. `disableFilenameBasedTypeAcquisition` ### 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. { "compilerOptions": {}, "files": [ "core.ts", "sys.ts", "types.ts", "scanner.ts", "parser.ts", "utilities.ts", "binder.ts", "checker.ts", "tsc.ts" ] } This is useful when you only have a small number of files and don’t need to use a glob to reference many files. If you need that then use `include`. * Default: `false` * Related: * `include` * `exclude` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### Extends - `extends` The value of `extends` is a string which contains a path to another configuration file to inherit from. The path may use Node.js style resolution. The configuration from the base file are loaded first, then overridden by those in the inheriting config file. All relative paths found in the configuration file will be resolved relative to the configuration file they originated in. It’s worth noting that `files`, `include`, and `exclude` from the inheriting config file _overwrite_ those from the base config file, and that circularity between configuration files is not allowed. Currently, the only top-level property that is excluded from inheritance is `references`. ##### Example `configs/base.json`: { "compilerOptions": { "noImplicitAny": true, "strictNullChecks": true } } `tsconfig.json`: { "extends": "./configs/base", "files": ["main.ts", "supplemental.ts"] } `tsconfig.nostrictnull.json`: { "extends": "./tsconfig", "compilerOptions": { "strictNullChecks": false } } Properties with relative paths found in the configuration file, which aren’t excluded from inheritance, will be resolved relative to the configuration file they originated in. * Default: `false` * Released: [2.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-1.html) ### 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. { "include": ["src/**/*", "tests/**/*"] } Which would include: . ├── scripts ⨯ │ ├── lint.ts ⨯ │ ├── update_deps.ts ⨯ │ └── utils.ts ⨯ ├── src ✓ │ ├── client ✓ │ │ ├── index.ts ✓ │ │ └── utils.ts ✓ │ ├── server ✓ │ │ └── index.ts ✓ ├── tests ✓ │ ├── app.test.ts ✓ │ ├── utils.ts ✓ │ └── tests.d.ts ✓ ├── package.json ├── tsconfig.json └── yarn.lock `include` and `exclude` support wildcard characters to make glob patterns: * `*` matches zero or more characters (excluding directory separators) * `?` matches any one character (excluding directory separators) * `**/` matches any directory nested to any level If 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` if `allowJs` is set to true). * Default: `[]` if `files` is specified; `**/*` otherwise. * Related: * `files` * `exclude` * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### Exclude - `exclude` Specifies an array of filenames or patterns that should be skipped when resolving `include`. **Important** : `exclude` _only_ changes which files are included as a result of the `include` setting. A file specified by `exclude` can still become part of your codebase due to an `import` statement in your code, a `types` inclusion, a `/// 5) { return true; } else { return false; } return true; } With `"allowUnreachableCode": false`: function fn(n: number) { if (n > 5) { return true; } else { return false; } return true; } This does not affect errors on the basis of code which _appears_ to be unreachable due to type analysis. * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### 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: function verifyAge(age: number) { // Forgot 'return' statement if (age > 18) { verified: true; } } * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### Always Strict - `alwaysStrict` Ensures that your files are parsed in the ECMAScript strict mode, and emit “use strict” for each source file. [ECMAScript strict](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Strict_mode) 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` if `strict`; `false` otherwise. * Related: * `strict` * Released: [2.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-1.html) ### Exact Optional Property Types - `exactOptionalPropertyTypes` With exactOptionalPropertyTypes enabled, TypeScript applies stricter rules around how it handles properties on `type` or `interfaces` 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. interface 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” and `undefined`. 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 as `colorThemeOverride` not being defined. For example, `"colorThemeOverride" in settings` would have different behavior with `undefined` as the key compared to not being defined. `exactOptionalPropertyTypes` makes TypeScript truly enforce the definition provided as an optional property: const settings = getUserSettings(); settings.colorThemeOverride = "dark"; settings.colorThemeOverride = "light";   // But not: settings.colorThemeOverride = undefined; * Recommended * Released: [4.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-4.html) ### 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`, or `throw`. This means you won’t accidentally ship a case fallthrough bug. const a: number = 6;   switch (a) { case 0: console.log("even"); case 1: console.log("odd"); break; } * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### 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: function fn(s) { // No error? console.log(s.subtr(3)); } fn(42); Turning on `noImplicitAny` however TypeScript will issue an error whenever it would have inferred `any`: function fn(s) { console.log(s.subtr(3)); } * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### 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: class Album { download() { // Default behavior } }   class SharedAlbum extends Album { 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: class Album { setup() { // Default behavior } }   class MLAlbum extends Album { setup() { // Override to get info from algorithm } }   class SharedAlbum extends Album { download() { // Override to get info from many sources } } In this case, TypeScript has provided no warning that `download` on `SharedAlbum` _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 keyword `override`. The following example has `noImplicitOverride` enabled, and you can see the error received when `override` is missing: class Album { setup() {} }   class MLAlbum extends Album { override setup() {} }   class SharedAlbum extends Album { setup() {} } * Released: [4.3](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-3.html) ### No Implicit Returns - `noImplicitReturns` When enabled, TypeScript will check all code paths in a function to ensure they return a value. function lookupHeadphonesManufacturer(color: "blue" | "black"): string { if (color === "blue") { return "beats"; } else { ("bose"); } } * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### 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` and `this.height` – but the context for `this` inside the function inside `getAreaFunction` is not the instance of the Rectangle. class Rectangle { width: number; height: number;   constructor(width: number, height: number) { this.width = width; this.height = height; }   getAreaFunction() { return function () { return this.width * this.height; }; } } * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### 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: interface GameSettings { // Known up-front properties speed: "fast" | "medium" | "slow"; quality: "high" | "low";   // Assume anything unknown to the interface // is a string. [key: string]: string; }   const settings = getSettings(); settings.speed; settings.quality;   // Unknown key accessors are allowed on // this object, and are `string` settings.username; Turning the flag on will raise an error because the unknown field uses dot syntax instead of indexed syntax. const settings = getSettings(); settings.speed; settings.quality;   // This would need to be settings["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: [4.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-2.html) ### 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. interface EnvironmentVars { NAME: string; OS: string;   // Unknown properties are covered by this index signature. [propName: string]: string; }   declare const env: EnvironmentVars;   // Declared as existing const sysName = env.NAME; const os = env.OS;   // Not declared, but because of the index // signature, then it is considered a string const nodeEnv = env.NODE_ENV; Turning on `noUncheckedIndexedAccess` will add `undefined` to any un-declared field in the type. declare const env: EnvironmentVars;   // Declared as existing const sysName = env.NAME; const os = env.OS;   // Not declared, but because of the index // signature, then it is considered a string const nodeEnv = env.NODE_ENV; * Released: [4.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-1.html) ### No Unused Locals - `noUnusedLocals` Report errors on unused local variables. const createKeyboard = (modelID: number) => { const defaultModelID = 23; return { type: "keyboard", modelID }; }; * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### No Unused Parameters - `noUnusedParameters` Report errors on unused parameters in functions. const createDefaultKeyboard = (modelID: number) => { const defaultModelID = 23; return { type: "keyboard", modelID: defaultModelID }; }; * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### 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: * `alwaysStrict` * `strictNullChecks` * `strictBindCallApply` * `strictBuiltinIteratorReturn` * `strictFunctionTypes` * `strictPropertyInitialization` * `noImplicitAny` * `noImplicitThis` * `useUnknownInCatchVariables` * Released: [2.3](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-3.html) ### Strict Bind Call Apply - `strictBindCallApply` When set, TypeScript will check that the built-in methods of functions `call`, `bind`, and `apply` are invoked with correct argument for the underlying function: // With strictBindCallApply on function fn(x: string) { return parseInt(x); }   const n1 = fn.call(undefined, "10");   const n2 = fn.call(undefined, false); Otherwise, these functions accept any arguments and will return `any`: // With strictBindCallApply off function fn(x: string) { return parseInt(x); }   // Note: No error; return type is 'any' const n = fn.call(undefined, false); * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [3.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-2.html) ### strictBuiltinIteratorReturn - `strictBuiltinIteratorReturn` Built-in iterators are instantiated with a `TReturn` type of undefined instead of `any`. * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [5.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-6.html) ### Strict Function Types - `strictFunctionTypes` When enabled, this flag causes functions parameters to be checked more correctly. Here’s a basic example with `strictFunctionTypes` off: function fn(x: string) { console.log("Hello, " + x.toLowerCase()); }   type StringOrNumberFunc = (ns: string | number) => void;   // Unsafe assignment let func: StringOrNumberFunc = fn; // Unsafe call - will crash func(10); With `strictFunctionTypes` _on_ , the error is correctly detected: function fn(x: string) { console.log("Hello, " + x.toLowerCase()); }   type StringOrNumberFunc = (ns: string | number) => void;   // Unsafe assignment is prevented let 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: type Methodish = { func(x: string | number): void; };   function fn(x: string) { console.log("Hello, " + x.toLowerCase()); }   // Ultimately an unsafe assignment, but not detected const m: Methodish = { func: fn, }; m.func(10); * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [2.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-6.html) ### Strict Null Checks - `strictNullChecks` When `strictNullChecks` is `false`, `null` and `undefined` are effectively ignored by the language. This can lead to unexpected errors at runtime. When `strictNullChecks` is `true`, `null` and `undefined` 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: declare const loggedInUsername: string;   const users = [ { name: "Oby", age: 12 }, { name: "Heera", age: 32 }, ];   const loggedInUser = users.find((u) => u.name === loggedInUsername); console.log(loggedInUser.age); Setting `strictNullChecks` to `true` will raise an error that you have not made a guarantee that the `loggedInUser` exists before trying to use it. declare const loggedInUsername: string;   const users = [ { name: "Oby", age: 12 }, { name: "Heera", age: 32 }, ];   const loggedInUser = users.find((u) => u.name === loggedInUsername); console.log(loggedInUser.age); The second example failed because the array’s `find` function looks a bit like this simplification: // When strictNullChecks: true type 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 result type Array = { find(predicate: (value: any, index: number) => boolean): S; }; * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### 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. class UserAccount { name: string; accountType = "user";   email: string; 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 potentially `undefined` which means it does not have to be set. * Recommended * Default: `true` if `strict`; `false` otherwise. * Related: * `strict` * Released: [2.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-7.html) ### 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` to `unknown`. Allowing for code like: try { // ... } catch (err: unknown) { // We have to verify err is an // error before using it as one. if (err instanceof Error) { 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` if `strict`; `false` otherwise. * Related: * `strict` * Released: [4.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-4.html) ## 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: /* app.css */ .cookie-banner { display: none; } // app.d.css.ts declare const css: { cookieBanner: string; }; export default css; // App.tsx import styles from "./app.css"; styles.cookieBanner; // string By 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 of `app.d.css.ts` \- however, this just worked through Node’s `require` resolution rules for CommonJS. Strictly speaking, the former is interpreted as a declaration file for a JavaScript file named `app.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` or `nodenext`. For more information, read up [the proposal for this feature](https://github.com/microsoft/TypeScript/issues/50133) and [its corresponding pull request](https://github.com/microsoft/TypeScript/pull/51435). * Released: [5.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-0.html) ### Allow Importing TS Extensions - `allowImportingTsExtensions` `--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. * Default: `true` if `rewriteRelativeImportExtensions`; `false` otherwise. * Released: [5.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-0.html) ### Allow Umd Global Access - `allowUmdGlobalAccess` 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: [3.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-5.html) ### 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.json With `"baseUrl": "./"`, TypeScript will look for files starting at the same folder as the `tsconfig.json`: import { 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 using `paths`. * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### Custom Conditions - `customConditions` `--customConditions` takes a list of additional [conditions](https://nodejs.org/api/packages.html#nested-conditions) that should succeed when TypeScript resolves from an [`exports`](https://nodejs.org/api/packages.html#exports) or [`imports`](https://nodejs.org/api/packages.html#imports) field of a `package.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: { "compilerOptions": { "target": "es2022", "moduleResolution": "bundler", "customConditions": ["my-condition"] } } Any time an `exports` or `imports` field is referenced in `package.json`, TypeScript will consider conditions called `my-condition`. So when importing from a package with the following `package.json` { // ... "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`, and `bundler` options for `--moduleResolution`. * Related: * `moduleResolution` * `resolvePackageJsonExports` * `resolvePackageJsonImports` * Released: [5.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-0.html) ### Module - `module` Sets the module system for the program. See the [theory behind TypeScript’s `module` option](../docs/handbook/modules/theory#the-module-output-format) and [its reference page](../docs/handbook/modules/reference#the-module-compiler- option) for more information. You very likely want `"nodenext"` for modern Node.js projects and `preserve` or `esnext` for code that will be bundled. Changing `module` affects `moduleResolution` which [also has a reference page](../docs/handbook/modules/reference#the-moduleresolution-compiler- option). Here’s some example output for this file: // @filename: index.ts import { valueOfPi } from "./constants";   export const twoPi = valueOfPi * 2; #### `CommonJS` "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.twoPi = void 0; const constants_1 = require("./constants"); exports.twoPi = constants_1.valueOfPi * 2;   #### `UMD` (function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "./constants"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.twoPi = void 0; const constants_1 = require("./constants"); exports.twoPi = constants_1.valueOfPi * 2; });   #### `AMD` define(["require", "exports", "./constants"], function (require, exports, constants_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.twoPi = void 0; exports.twoPi = constants_1.valueOfPi * 2; });   #### `System` System.register(["./constants"], function (exports_1, context_1) { "use strict"; var constants_1, twoPi; var __moduleName = context_1 && context_1.id; return { setters: [ function (constants_1_1) { constants_1 = constants_1_1; } ], execute: function () { exports_1("twoPi", twoPi = constants_1.valueOfPi * 2); } }; });   #### `ESNext` import { valueOfPi } from "./constants"; export const twoPi = valueOfPi * 2;   #### `ES2015`/`ES6`/`ES2020`/`ES2022` import { valueOfPi } from "./constants"; export const twoPi = valueOfPi * 2;   In addition to the base functionality of `ES2015`/`ES6`, `ES2020` adds support for [dynamic `import`s](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Operators/import), and [`import.meta`](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Operators/import.meta) while `ES2022` further adds support for [top level `await`](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Operators/await#top_level_await). #### `node16`/`node18`/`nodenext` The `node16`, `node18`, and `nodenext` modes integrate with Node’s [native ECMAScript Module support](https://nodejs.org/api/esm.html). The emitted JavaScript uses either `CommonJS` or `ES2020` output depending on the file extension and the value of the `type` setting in the nearest `package.json`. Module resolution also works differently. You can learn more in the [handbook](../docs/handbook/esm-node) and [Modules Reference](../docs/handbook/modules/reference#node16-node18-nodenext). * `node16` is available from TypeScript 4.7 * `node18` is available from TypeScript 5.8 as a replacement for `node16`, with added support for import attributes. * `nodenext` is available from TypeScript 4.7, but its behavior changes with the latest stable versions of Node.js. As of TypeScript 5.8, `nodenext` supports `require` of ECMAScript modules. #### `preserve` In `--module preserve` ([added](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-4.html#support-for-require-calls-in---moduleresolution- bundler-and---module-preserve) in TypeScript 5.4), ECMAScript imports and exports written in input files are preserved in the output, and CommonJS-style `import x = require("...")` and `export = ...` statements are emitted as CommonJS `require` and `module.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). import { 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 setting `noEmit`? TypeScript’s type checking and module > resolution behavior are affected by the module format that it _would_ emit. > Setting `module` 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. #### `None` "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` if `target` is `ES5`; `ES6`/`ES2015` otherwise. * Allowed: * `none` * `commonjs` * `amd` * `umd` * `system` * `es6`/`es2015` * `es2020` * `es2022` * `esnext` * `node16` * `node18` * `nodenext` * `preserve` * Related: * `moduleResolution` * `esModuleInterop` * `allowImportingTsExtensions` * `allowArbitraryExtensions` * `resolveJsonModule` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### 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 CommonJS `require`, which resolve using different algorithms. These `moduleResolution` values, when combined with the corresponding `module` values, picks the right algorithm for each resolution based on whether Node.js will see an `import` or `require` in the output JavaScript code. * `'node10'` (previously called `'node'`) for Node.js versions older than v10, which only support CommonJS `require`. You probably won’t need to use `node10` in modern code. * `'bundler'` for use with bundlers. Like `node16` and `nodenext`, 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. There are reference pages explaining the [theory behind TypeScript’s module resolution](../docs/handbook/modules/theory#module-resolution) and the [details of each option](../docs/handbook/modules/reference#the- moduleresolution-compiler-option). * Default: `Node10` if `module` is `CommonJS`; `Node16` if `module` is `Node16` or `Node18`; `NodeNext` if `module` is `NodeNext`; `Bundler` if `module` is `Preserve`; `Classic` otherwise. * Allowed: * `classic` * `node10`/`node` * `node16` * `nodenext` * `bundler` * Related: * `module` * `paths` * `baseUrl` * `rootDirs` * `moduleSuffixes` * `customConditions` * `resolvePackageJsonExports` * `resolvePackageJsonImports` * Released: [1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html) ### Module Suffixes - `moduleSuffixes` Provides a way to override the default list of file name suffixes to search when resolving a module. { "compilerOptions": { "moduleSuffixes": [".ios", ".native", ""] } } Given the above configuration, an import like the following: import * 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 `""` in `moduleSuffixes` 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: [4.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-7.html) ### No Resolve - `noResolve` By default, TypeScript will examine the initial set of files for `import` and `= 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](https://www.npmjs.com/package/tslib) via `importHelpers` to reduce the amount of inline JavaScript too: "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 if `Symbol.iterator` is not present in the runtime. #### Example: Effects on Array Spreads This is an array spread: // Make a new array whose elements are 1 followed by the elements of arr2 const arr = [1, ...arr2]; Based on the description, it sounds easy to downlevel to ES5: // The same, right? const arr = [1].concat(arr2); However, this is observably different in certain rare cases. For example, if 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. // Make an array where the element at index 1 is missing let 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 use `Symbol.iterator` (if present) to more accurately emulate ES 6 behavior. * Related: * `importHelpers` * Released: [2.3](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-3.html) ### Emit BOM - `emitBOM` Controls whether TypeScript will emit a [byte order mark (BOM)](https://wikipedia.org/wiki/Byte_order_mark) 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. * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Emit Declaration Only - `emitDeclarationOnly` _Only_ emit `.d.ts` files; do not emit `.js` files. 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: * `declaration` * Released: [2.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-8.html) ### 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](https://www.npmjs.com/package/tslib) module. You will need to ensure that the `tslib` module is able to be imported at runtime. This only affects modules; global script files will not attempt to import modules. For example, with this TypeScript: export function fn(arr: number[]) { const arr2 = [1, ...arr]; } Turning on `downlevelIteration` and `importHelpers` is still false: var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __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` and `importHelpers`: import { __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: * `noEmitHelpers` * `downlevelIteration` * Released: [2.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-1.html) ### 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: const helloWorld = "hi"; console.log(helloWorld); Converts to this JavaScript: "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. "use strict"; const helloWorld = "hi"; console.log(helloWorld); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMifQ== * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### 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’s `sourcesContent` property). This is often useful in the same cases as `inlineSourceMap`. Requires either `sourceMap` or `inlineSourceMap` to be set. For example, with this TypeScript: const helloWorld = "hi"; console.log(helloWorld); By default converts to this JavaScript: "use strict"; const helloWorld = "hi"; console.log(helloWorld);   Then enable building it with `inlineSources` and `inlineSourceMap` 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 in `inlineSourceMap` because the source-map now contains the original source code also. "use strict"; const helloWorld = "hi"; console.log(helloWorld); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBoZWxsb1dvcmxkID0gXCJoaVwiO1xuY29uc29sZS5sb2coaGVsbG9Xb3JsZCk7Il19 * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### 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: { "compilerOptions": { "sourceMap": true, "mapRoot": "https://my-website.com/debug/sourcemaps/" } } Would declare that `index.js` will have sourcemaps at `https://my- website.com/debug/sourcemaps/index.js.map`. * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### New Line - `newLine` Specify the end of line sequence to be used when emitting files: ‘CRLF’ (dos) or ‘LF’ (unix). * Default: `lf` * Allowed: * `crlf` * `lf` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### 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](https://babeljs.io), or [swc](https://github.com/swc-project/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. * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### No Emit Helpers - `noEmitHelpers` 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 a `await`-like function and `generator`-like function to run: const getAPI = async (url: string) => { // Get API return {}; }; Which creates quite a lot of JavaScript: "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 = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["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 API return [2 /*return*/, {}]; }); }); };   Which can be switched out with your own globals via this flag: "use strict"; var getAPI = function (url) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { // Get API return [2 /*return*/, {}]; }); }); };   * Related: * `importHelpers` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### 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: [1.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-4.html) ### Out Dir - `outDir` If specified, `.js` (as well as `.d.ts`, `.js.map`, etc.) files will be emitted into this directory. The directory structure of the original source files is preserved; see `rootDir` if the computed root is not what you intended. If not specified, `.js` files will be emitted in the same directory as the `.ts` files they were generated from: $ tsc example ├── index.js └── index.ts With a `tsconfig.json` like this: { "compilerOptions": { "outDir": "dist" } } Running `tsc` with these settings moves the files into the specified `dist` folder: $ tsc example ├── dist │ └── index.js ├── index.ts └── tsconfig.json * Related: * `out` * `outFile` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Out File - `outFile` If specified, all _global_ (non-module) files will be concatenated into the single output file specified. If `module` is `system` or `amd`, all module files will also be concatenated into this file after all global content. Note: `outFile` cannot be used unless `module` is `None`, `System`, or `AMD`. This option _cannot_ be used to bundle CommonJS or ES6 modules. * Related: * `out` * `outDir` * Released: [1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html) ### 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: const enum Album { JimmyEatWorldFutures = 1, TubRingZooHypothesis = 2, DogFashionDiscoAdultery = 3, }   const selectedAlbum = Album.JimmyEatWorldFutures; if (selectedAlbum === Album.JimmyEatWorldFutures) { console.log("That is a great choice."); } The default `const enum` behavior is to convert any `Album.Something` to the corresponding number literal, and to remove a reference to the enum from the JavaScript completely. "use strict"; const selectedAlbum = 1 /* Album.JimmyEatWorldFutures */; if (selectedAlbum === 1 /* Album.JimmyEatWorldFutures */) { console.log("That is a great choice."); }   With `preserveConstEnums` set to `true`, the `enum` exists at runtime and the numbers are still emitted. "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` if `isolatedModules`; `false` otherwise. * Released: [1.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-4.html) ### Remove Comments - `removeComments` Strips all comments from TypeScript files when converting into JavaScript. Defaults to `false`. For example, this is a TypeScript file which has a JSDoc comment: /** The translation of 'Hello world' into Portuguese */ export const helloWorldPTBR = "Olá Mundo"; When `removeComments` is set to `true`: export const helloWorldPTBR = "Olá Mundo";   Without setting `removeComments` or having it as `false`: /** The translation of 'Hello world' into Portuguese */ export const helloWorldPTBR = "Olá Mundo";   This means that your comments will show up in the JavaScript code. * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Source Map - `sourceMap` Enables the generation of [sourcemap files](https://developer.mozilla.org/docs/Tools/Debugger/How_to/Use_a_source_map). 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: // helloWorld.ts export declare const helloWorld = "hi"; Compiling with `sourceMap` set to `true` creates the following JavaScript file: // helloWorld.js "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.helloWorld = "hi"; //# sourceMappingURL=// helloWorld.js.map And this also generates this json map: // helloWorld.js.map { "version": 3, "file": "ex.js", "sourceRoot": "", "sources": ["../ex.ts"], "names": [], "mappings": ";;AAAa,QAAA,UAAU,GAAG,IAAI,CAAA" } * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Source Root - `sourceRoot` 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: { "compilerOptions": { "sourceMap": true, "sourceRoot": "https://my-website.com/debug/source/" } } Would declare that `index.js` will have a source file at `https://my- website.com/debug/source/index.ts`. * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Strip Internal - `stripInternal` 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 your `d.ts` files, look at [api-extractor](https://api-extractor.com). /** * Days available in a week * @internal */ export const daysInAWeek = 7;   /** Calculate how much someone earns in a week */ export function weeklySalary(dayRate: number) { return daysInAWeek * dayRate; } With the flag set to `false` (default): /** * 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 to `true` the `d.ts` emitted will be redacted. /** Calculate how much someone earns in a week */ export declare function weeklySalary(dayRate: number): number;   The JavaScript output is still the same. * Internal * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ## 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: // @filename: card.js export const defaultCardDeck = "Heart"; When imported into a TypeScript file will raise an error: // @filename: index.ts import { defaultCardDeck } from "./card";   console.log(defaultCardDeck); Imports fine with `allowJs` enabled: // @filename: index.ts import { 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` and `emitDeclarationOnly` to [create declarations for JS files](../docs/handbook/declaration-files/dts- from-js). * Related: * `checkJs` * `emitDeclarationOnly` * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### Check JS - `checkJs` Works in tandem with `allowJs`. When `checkJs` is enabled then errors are reported in JavaScript files. This is the equivalent of including `// @ts- check` at the top of all JavaScript files which are included in your project. For example, this is incorrect JavaScript according to the `parseFloat` type definition which comes with TypeScript: // parseFloat only takes a string module.exports.pi = parseFloat(3.142); When imported into a TypeScript module: // @filename: constants.js module.exports.pi = parseFloat(3.142);   // @filename: index.ts import { 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. // @filename: constants.js module.exports.pi = parseFloat(3.142);   // @filename: index.ts import { pi } from "./constants"; console.log(pi); * Related: * `allowJs` * `emitDeclarationOnly` * Released: [2.3](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-3.html) ### 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 your `node_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. * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ## Editor Support ### Disable Size Limit - `disableSizeLimit` To avoid a possible memory bloat issues when working with very large JavaScript projects, there is an upper limit to the amount of memory TypeScript will allocate. Turning this flag on will remove the limit. * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### Plugins - `plugins` List of language service plugins to run inside the editor. Language service plugins are a way to provide additional information to a user based on existing TypeScript files. They can enhance existing messages between TypeScript and an editor, or to provide their own error messages. For example: * [ts-sql-plugin](https://github.com/xialvjun/ts-sql-plugin#readme) — Adds SQL linting with a template strings SQL builder. * [typescript-styled-plugin](https://github.com/Microsoft/typescript-styled-plugin) — Provides CSS linting inside template strings . * [typescript-eslint-language-service](https://github.com/Quramy/typescript-eslint-language-service) — Provides eslint error messaging and fix-its inside the compiler’s output. * [ts-graphql-plugin](https://github.com/Quramy/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](https://code.visualstudio.com/api/references/contribution- points#contributes.typescriptServerPlugins), and so you may have some running in your editor without needing to define them in your `tsconfig.json`. * Released: [2.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-2.html) ## Interop Constraints ### Allow Synthetic Default Imports - `allowSyntheticDefaultImports` When set to true, `allowSyntheticDefaultImports` allows you to write an import like: import React from "react"; instead of: import * as React from "react"; When the module **does not** explicitly specify a default export. For example, without `allowSyntheticDefaultImports` as true: // @filename: utilFunctions.js const getStringLength = (str) => str.length;   module.exports = { getStringLength, };   // @filename: index.ts import utils from "./utilFunctions";   const count = 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: // @filename: utilFunctions.js const 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` if `esModuleInterop` is enabled, `module` is `system`, or `moduleResolution` is `bundler`; `false` otherwise. * Related: * `esModuleInterop` * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### Erasable Syntax Only - `erasableSyntaxOnly` Node.js [supports running TypeScript files directly](https://nodejs.org/api/typescript.html#type-stripping) as of v23.6; however, only TypeScript-specific syntax that does not have runtime semantics are supported under this mode. In other words, it must be possible to easily _erase_ any TypeScript-specific syntax from a file, leaving behind a valid JavaScript file. That means the following constructs are not supported: * `enum` declarations * `namespace`s and `module`s with runtime code * parameter properties in classes * Non-ECMAScript `import =` and `export =` assignments // ❌ error: An `import ... = require(...)` alias import foo = require("foo"); // ❌ error: A namespace with runtime code. namespace container { foo.method(); export type Bar = string; } // ❌ error: An `import =` alias import Bar = container.Bar; class Point { // ❌ error: Parameter properties constructor(public x: number, public y: number) {} } // ❌ error: An `export =` assignment. export = Point; // ❌ error: An enum declaration. enum Direction { Up, Down, Left, Right, } Similar tools like [ts-blank-space](https://github.com/bloomberg/ts-blank- space) or [Amaro](https://github.com/nodejs/amaro) (the underlying library for type-stripping in Node.js) have the same limitations. These tools will provide helpful error messages if they encounter code that doesn’t meet these requirements, but you still won’t find out your code doesn’t work until you actually try to run it. The `--erasableSyntaxOnly` flag will cause TypeScript to error on most TypeScript-specific constructs that have runtime behavior. class C { constructor(public x: number) { } // ~~~~~~~~~~~~~~~~ // error! This syntax is not allowed when 'erasableSyntaxOnly' is enabled. } } Typically, you will want to combine this flag with the `--verbatimModuleSyntax`, which ensures that a module contains the appropriate import syntax, and that import elision does not take place. ### 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 as `const moment = require("moment")` * a default import like `import moment from "moment"` acts the same as `const 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: import * as fs from "fs"; import _ from "lodash"; fs.readFileSync("file.txt", "utf8"); _.chunk(["a", "b", "c", "d"], 2); With `esModuleInterop` disabled: "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 to `true`: "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 () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __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](https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) (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 disable `esModuleInterop`. _Note_ : You can make JS emit terser by enabling `importHelpers`: "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 enable `allowSyntheticDefaultImports`. * Recommended * Default: `true` if `module` is `node16`, `nodenext`, or `preserve`; `false` otherwise. * Related: * `allowSyntheticDefaultImports` * Released: [2.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-7.html) ### 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` * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### isolatedDeclarations - `isolatedDeclarations` Require sufficient annotation on exports so other tools can trivially generate declaration files. For more information, see the [5.5 release notes](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-5.html#isolated-declarations) * Released: [5.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-5.html) ### 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](https://babeljs.io) 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 and `namespace`s. Setting the `isolatedModules` flag tells TypeScript to warn you if you write certain code that can’t be correctly interpreted by a single-file transpilation process. It does not change the behavior of your code, or otherwise change the behavior of TypeScript’s checking and emitting process. Some examples of code which does not work when `isolatedModules` is enabled. #### Exports of Non-Value Identifiers In TypeScript, you can import a _type_ and then subsequently export it: import { someType, someFunction } from "someModule";   someFunction();   export { someType, someFunction }; Because there’s no value for `someType`, the emitted `export` will not try to export it (this would be a runtime error in JavaScript): export { someFunction }; Single-file transpilers don’t know whether `someType` produces a value or not, so it’s an error to export a name that only refers to a type. #### Non-Module Files If `isolatedModules` is set, namespaces are only allowed in _modules_ (which means it has some form of `import`/`export`). An error occurs if a namespace is found in a non-module file: namespace Instantiated { export const x = 1; } This restriction doesn’t apply to `.d.ts` files. #### References to `const enum` members In TypeScript, when you reference a `const enum` member, the reference is replaced by its actual value in the emitted JavaScript. Changing this TypeScript: declare const enum Numbers { Zero = 0, One = 1, } console.log(Numbers.Zero + Numbers.One); To this JavaScript: "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 no `Numbers` object at runtime). Because of this, when `isolatedModules` is set, it is an error to reference an ambient `const enum` member. * Default: `true` if `verbatimModuleSyntax`; `false` otherwise. * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### Preserve Symlinks - `preserveSymlinks` 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’s `preserveSymlinks` to true parallels setting Webpack’s `resolve.symlinks` to false, and vice-versa). With this enabled, references to modules and packages (e.g. `import`s and `/// ` 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. * Released: [2.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-5.html) ### Verbatim Module Syntax - `verbatimModuleSyntax` By default, TypeScript does something called _import elision_. Basically, if you write something like import { 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: export 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 export { Car } from "./car"; should be preserved or dropped. If `Car` is declared with something like a `class`, then it can be preserved in the resulting JavaScript file. But if `Car` is only declared as a `type` alias or `interface`, then the JavaScript file shouldn’t export `Car` 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 the `type` modifier. // This statement can be dropped entirely in JS output import type * as car from "./car"; // The named import/export 'Car' can be dropped in JS output import { 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 between `type` and plain imports and exports. So TypeScript has the flag `--importsNotUsedAsValues` to make sure you use the `type` 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 a `type` modifier are left around. Anything that uses the `type` modifier is dropped entirely. // 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 `import`s and `export`s won’t be rewritten to `require` 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 uses `require` and `module.exports`, you’ll have to use TypeScript’s module syntax that predates ES2015: Input TypeScript | Output JavaScript ---|--- import foo = require("foo"); | const foo = require("foo"); function foo() {} function bar() {} function baz() {} export = { foo, bar, baz, }; | function 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 in `package.json`](https://nodejs.org/api/packages.html#type) 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](https://github.com/microsoft/TypeScript/pull/52203) and [its proposal issue](https://github.com/microsoft/TypeScript/issues/51479). * Released: [5.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-0.html) ## Backwards Compatibility ### Charset - `charset` 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` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### 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 dropping `import` statements which only reference types. * `preserve`: Preserves all `import` 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 an `import` statement which should never be emitted into JavaScript. * Default: `remove` * Allowed: * `remove` * `preserve` * `error` * Related: * `preserveValueImports` * `verbatimModuleSyntax` * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Keyof Strings Only - `keyofStringsOnly` This flag changes the `keyof` type operator to return `string` instead of `string | 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](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-9.html#support-number-and-symbol-named-properties-with- keyof-and-mapped-types). * Deprecated * Released: [2.9](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-9.html) ### 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. * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### No Strict Generic Checks - `noStrictGenericChecks` TypeScript will unify type parameters when comparing two generic functions. type A = (x: T, y: U) => [T, U]; type B = (x: S, y: S) => [S, S];   function f(a: A, b: B) { b = a; // Ok a = b; // Error } This flag can be used to remove that check. * Released: [2.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-5.html) ### 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: * `outDir` * `outFile` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### 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: import { 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: * `isolatedModules` * `importsNotUsedAsValues` * `verbatimModuleSyntax` * Released: [4.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-5.html) ### Suppress Excess Property Errors - `suppressExcessPropertyErrors` This disables reporting of excess property errors, such as the one shown in the following example: type Point = { x: number; y: number }; const p: Point = { x: 1, y: 3, m: 10 }; This flag was added to help people migrate to the stricter checking of new object literals in [TypeScript 1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html#stricter-object-literal-assignment-checks). We don’t recommend using this flag in a modern codebase, you can suppress one- off cases where you need it using `// @ts-ignore`. * Released: [1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html) ### Suppress Implicit Any Index Errors - `suppressImplicitAnyIndexErrors` Turning `suppressImplicitAnyIndexErrors` on suppresses reporting the error about implicit anys when indexing into objects, as shown in the following example: const obj = { x: 10 }; console.log(obj["foo"]); Using `suppressImplicitAnyIndexErrors` is quite a drastic approach. It is recommended to use a `@ts-ignore` comment instead: const obj = { x: 10 }; // @ts-ignore console.log(obj["foo"]); * Related: * `noImplicitAny` * Released: [1.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-4.html) ## Language and Environment ### Emit Decorator Metadata - `emitDecoratorMetadata` Enables experimental support for emitting type metadata for decorators which works with the module [`reflect- metadata`](https://www.npmjs.com/package/reflect-metadata). For example, here is the TypeScript 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(); With `emitDecoratorMetadata` not set to true (default) the emitted JavaScript is: "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: "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: * `experimentalDecorators` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### Experimental Decorators - `experimentalDecorators` Enables [experimental support for decorators](https://github.com/tc39/proposal-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](../docs/handbook/decorators). * Related: * `emitDecoratorMetadata` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### JSX - `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: export const HelloWorld = () =>

Hello world

; React: `"react-jsx"`[[1]](https://reactjs.org/blog/2020/09/22/introducing-the- new-jsx-transform.html) import { jsx as _jsx } from "react/jsx-runtime"; export const HelloWorld = () => _jsx("h1", { children: "Hello world" });   React dev transform: `"react- jsxdev"`[[1]](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx- transform.html) import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime"; const _jsxFileName = "/home/runner/work/TypeScript-Website/TypeScript-Website/packages/typescriptlang-org/index.tsx"; export const HelloWorld = () => _jsxDEV("h1", { children: "Hello world" }, void 0, false, { fileName: _jsxFileName, lineNumber: 9, columnNumber: 32 }, this);   Preserve: `"preserve"` import React from 'react'; export const HelloWorld = () =>

Hello world

;   React Native: `"react-native"` import React from 'react'; export const HelloWorld = () =>

Hello world

;   Legacy React runtime: `"react"` import React from 'react'; export const HelloWorld = () => React.createElement("h1", null, "Hello world");   This option can be used on a per-file basis too using an `@jsxRuntime` comment. Always use the classic runtime (`"react"`) for this file: /* @jsxRuntime classic */ export const HelloWorld = () =>

Hello world

; Always use the automatic runtime (`"react-jsx"`) for this file: /* @jsxRuntime automatic */ export const HelloWorld = () =>

Hello world

; * Allowed: * `preserve` * `react` * `react-native` * `react-jsx` * `react-jsxdev` * Related: * `jsxFactory` * `jsxFragmentFactory` * `jsxImportSource` * Released: [1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html) ### 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 using `preact`. For example, this TSX file: import { h } from "preact"; const HelloWorld = () =>
Hello
; With `jsxFactory: "h"` looks like: const 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](https://babeljs.io/docs/en/babel-plugin-transform-react- jsx#custom). /** @jsx h */ import { h } from "preact";   const HelloWorld = () =>
Hello
; 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`. * Default: `React.createElement` * Allowed: * Any identifier or dotted identifier. * Related: * `jsx` * `jsxFragmentFactory` * `jsxImportSource` * Released: [2.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-2.html) ### 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: { "compilerOptions": { "target": "esnext", "module": "commonjs", "jsx": "react", "jsxFactory": "h", "jsxFragmentFactory": "Fragment" } } This TSX file: import { h, Fragment } from "preact"; const HelloWorld = () => ( <>
Hello
); Would look like: const 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](https://babeljs.io/docs/en/babel-plugin-transform- react-jsx#fragments). For example: /** @jsx h */ /** @jsxFrag Fragment */   import { h, Fragment } from "preact";   const HelloWorld = () => ( <>
Hello
); * Default: `React.Fragment` * Related: * `jsx` * `jsxFactory` * `jsxImportSource` * Released: [4.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-0.html) ### JSX Import Source - `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](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx- transform.html) the library supports a new form of JSX transformation via a separate import. For example with this code: import React from "react"; function App() { return

Hello World

; } Using this TSConfig: { "compilerOptions": { "target": "esnext", "module": "commonjs", "jsx": "react-jsx" } } The emitted JavaScript from TypeScript is: "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: { "compilerOptions": { "target": "esnext", "module": "commonjs", "jsx": "react-jsx", "jsxImportSource": "preact", "types": ["preact"] } } Which generates code like: function App() { return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" }); }   Alternatively, you can use a per-file pragma to set this option, for example: /** @jsxImportSource preact */ export function App() { return

Hello World

; } 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. * Default: `react` * Related: * `jsx` * `jsxFactory` * Released: [4.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-1.html) ### Lib - `lib` TypeScript includes a default set of type definitions for built-in JS APIs (like `Math`), as well as type definitions for things found in browser environments (like `document`). TypeScript also includes APIs for newer JS features matching the `target` you specify; for example the definition for `Map` is available if `target` is `ES6` or newer. You may want to change these for a few reasons: * Your program doesn’t run in a browser, so you don’t want the `"dom"` type definitions * Your runtime platform provides certain JavaScript API objects (maybe through polyfills), but doesn’t yet support the full syntax of a given ECMAScript version * You have polyfills or native implementations for some, but not all, of a higher level ECMAScript version In TypeScript 4.5, lib files can be overridden by npm modules, find out more [in the blog](https://devblogs.microsoft.com/typescript/announcing- typescript-4-5-beta/#supporting-lib-from-node_modules). ### High Level libraries Name | Contents ---|--- `ES5` | Core definitions for all ES5 functionality `ES2015` | Additional APIs available in ES2015 (also known as ES6) - `array.find`, `Promise`, `Proxy`, `Symbol`, `Map`, `Set`, `Reflect`, etc. `ES6` | Alias for “ES2015” `ES2016` | Additional APIs available in ES2016 - `array.include`, etc. `ES7` | Alias for “ES2016” `ES2017` | Additional APIs available in ES2017 - `Object.entries`, `Object.values`, `Atomics`, `SharedArrayBuffer`, `date.formatToParts`, typed arrays, etc. `ES2018` | Additional APIs available in ES2018 - `async` iterables, `promise.finally`, `Intl.PluralRules`, `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. `ES2023` | Additional APIs available in ES2023 - `array.with`, `array.findLast`, `array.findLastIndex`, `array.toSorted`, `array.toReversed`, etc. `ESNext` | Additional APIs available in ESNext - This changes as the JavaScript specification evolves `DOM` | [DOM](https://developer.mozilla.org/docs/Glossary/DOM) definitions - `window`, `document`, etc. `WebWorker` | APIs available in [WebWorker](https://developer.mozilla.org/docs/Web/API/Web_Workers_API/Using_web_workers) contexts `ScriptHost` | APIs for the [Windows Script Hosting System](https://wikipedia.org/wiki/Windows_Script_Host) ### 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](https://github.com/microsoft/TypeScript/tree/main/src/lib). * Related: * `noLib` * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### Lib Replacement - `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](https://www.npmjs.com/package/@types/web?activeTab=readme) with the following `package.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`. * Default: `true` ### Module Detection - `moduleDetection` This setting controls how TypeScript determines whether a file is a [script or a module](../docs/handbook/modules/theory#scripts-and-modules-in-javascript). 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. * Default: "auto": Treat files with imports, exports, import.meta, jsx (with jsx: react- jsx), or esm format (with module: node16+) as modules. * Allowed: * `legacy` * `auto` * `force` * Released: [4.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-7.html) ### 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`, and `String`. It is expected that if you use `noLib` you will be including your own type definitions for these. * Related: * `lib` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### React Namespace - `reactNamespace` Use `jsxFactory` instead. Specify the object invoked for `createElement` when targeting `react` for TSX files. * Default: `React` * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ### Target - `target` Modern browsers support all ES6 features, so `ES6` is a good choice. You might choose to set a lower target if your code is deployed to older environments, or a higher target if your code is guaranteed to run in newer environments. The `target` setting changes which JS features are downleveled and which are left intact. For example, an arrow function `() => this` will be turned into an equivalent `function` expression if `target` is ES5 or lower. Changing `target` also changes the default value of `lib`. You may “mix and match” `target` and `lib` settings as desired, but you could just set `target` for convenience. For developer platforms like Node 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](https://github.com/tsconfig/bases#centralized- recommendations-for-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: `ES5` * Allowed: * `es3` * `es5` * `es6`/`es2015` * `es2016` * `es2017` * `es2018` * `es2019` * `es2020` * `es2021` * `es2022` * `es2023` * `es2024` * `esnext` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### 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](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html#the-usedefineforclassfields-flag-and-the-declare- property-modifier). * Default: `true` if `target` is `ES2022` or higher, including `ESNext`; `false` otherwise. * Released: [3.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html) ## 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 * Related: * `extendedDiagnostics` * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Explain Files - `explainFiles` Print names of files which TypeScript sees as a part of your project and the reason they are part of the compilation. For example, with this project of just a single `index.ts` file example ├── index.ts ├── package.json └── tsconfig.json Using a `tsconfig.json` which has `explainFiles` set to true: { "compilerOptions": { "target": "es5", "module": "commonjs", "explainFiles": true } } Running TypeScript against this folder would have output like this: ❯ tsc node_modules/typescript/lib/lib.d.ts Default library for target 'es5' node_modules/typescript/lib/lib.es5.d.ts Library referenced via 'es5' from file 'node_modules/typescript/lib/lib.d.ts' node_modules/typescript/lib/lib.dom.d.ts Library referenced via 'dom' from file 'node_modules/typescript/lib/lib.d.ts' node_modules/typescript/lib/lib.webworker.importscripts.d.ts Library referenced via 'webworker.importscripts' from file 'node_modules/typescript/lib/lib.d.ts' node_modules/typescript/lib/lib.scripthost.d.ts Library referenced via 'scripthost' from file 'node_modules/typescript/lib/lib.d.ts' index.ts Matched by include pattern '**/*' in 'tsconfig.json' The output above show: * The initial lib.d.ts lookup based on `target`, and the chain of `.d.ts` files which are referenced * The `index.ts` file located via the default pattern of `include` This option is intended for debugging how a file has become a part of your compile. * Released: [4.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-2.html) ### Extended Diagnostics - `extendedDiagnostics` You can use this flag to discover where TypeScript is spending its time when compiling. This is a tool used for understanding the performance characteristics of your codebase overall. You can learn more about how to measure and understand the output in the performance [section of the wiki](https://github.com/microsoft/TypeScript/wiki/Performance). * Related: * `diagnostics` * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### Generate CPU Profile - `generateCpuProfile` This option gives you the chance to have TypeScript emit a v8 CPU profile during the compiler run. The CPU profile can provide insight into why your builds may be slow. This option can only be used from the CLI via: `--generateCpuProfile tsc- output.cpuprofile`. npm run tsc --generateCpuProfile tsc-output.cpuprofile This file can be opened in a chromium based browser like Chrome or Edge Developer in [the CPU profiler](https://developers.google.com/web/tools/chrome-devtools/rendering- tools/js-execution) section. You can learn more about understanding the compilers performance in the [TypeScript wiki section on performance](https://github.com/microsoft/TypeScript/wiki/Performance). * Default: `profile.cpuprofile` * Released: [3.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html) ### generateTrace - `generateTrace` Generates an event trace and a list of types. * Released: [4.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-1.html) ### List Emitted Files - `listEmittedFiles` Print names of generated files part of the compilation to the terminal. This flag is useful in two cases: * You want to transpile TypeScript as a part of a build chain in the terminal where the filenames are processed in the next command. * You are not sure that TypeScript has included a file you expected, as a part of debugging the file inclusion settings. For example: example ├── index.ts ├── package.json └── tsconfig.json With: { "compilerOptions": { "declaration": true, "listEmittedFiles": true } } Would echo paths like: $ npm run tsc path/to/example/index.js path/to/example/index.d.ts Normally, TypeScript would return silently on success. * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ### List Files - `listFiles` Print names of files part of the compilation. This is useful when you are not sure that TypeScript has included a file you expected. For example: example ├── index.ts ├── package.json └── tsconfig.json With: { "compilerOptions": { "listFiles": true } } Would echo paths like: $ npm run tsc path/to/example/node_modules/typescript/lib/lib.d.ts path/to/example/node_modules/typescript/lib/lib.es5.d.ts path/to/example/node_modules/typescript/lib/lib.dom.d.ts path/to/example/node_modules/typescript/lib/lib.webworker.importscripts.d.ts path/to/example/node_modules/typescript/lib/lib.scripthost.d.ts path/to/example/index.ts Note if using TypeScript 4.2, prefer `explainFiles` which offers an explanation of why a file was added too. * Related: * `explainFiles` * Released: [1.5](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-5.html) ### noCheck - `noCheck` Disable full type checking (only critical parse and emit errors will be reported). * Released: [5.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-5-6.html) ### Trace Resolution - `traceResolution` When you are trying to debug why a module isn’t being included. You can set `traceResolution` to `true` to have TypeScript print information about its resolution process for each processed file. * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ## Projects ### Composite - `composite` The `composite` option enforces certain constraints which make it possible for build tools (including TypeScript itself, under `--build` mode) to quickly determine if a project has been built yet. When this setting is on: * The `rootDir` setting, if not explicitly set, defaults to the directory containing the `tsconfig.json` file. * All implementation files must be matched by an `include` pattern or listed in the `files` array. If this constraint is violated, `tsc` will inform you which files weren’t specified. * `declaration` defaults to `true` You can find documentation on TypeScript projects in [the handbook](../docs/handbook/project-references). * Related: * `incremental` * `tsBuildInfoFile` * Released: [3.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-0.html) ### Disable Referenced Project Load - `disableReferencedProjectLoad` In multi-project TypeScript programs, TypeScript will load all of the available projects into memory in order to provide accurate results for editor responses which require a full knowledge graph like ‘Find All References’. If your project is large, you can use the flag `disableReferencedProjectLoad` to disable the automatic loading of all projects. Instead, projects are loaded dynamically as you open files through your editor. * Released: [4.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-0.html) ### Disable Solution Searching - `disableSolutionSearching` When working with [composite TypeScript projects](../docs/handbook/project- references), this option provides a way to declare that you do not want a project to be included when using features like _find all references_ or _jump to definition_ in an editor. This flag is something you can use to increase responsiveness in large composite projects. * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Disable Source Project Reference Redirect - `disableSourceOfProjectReferenceRedirect` When working with [composite TypeScript projects](../docs/handbook/project- references), this option provides a way to go [back to the pre-3.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html#build-free-editing-with-project-references) behavior where d.ts files were used to as the boundaries between modules. In 3.7 the source of truth is now your TypeScript files. * Released: [3.7](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-7.html) ### Incremental - `incremental` Tells TypeScript to save information about the project graph from the last compilation to files stored on disk. This creates a series of `.tsbuildinfo` files in the same folder as your compilation output. They are not used by your JavaScript at runtime and can be safely deleted. You can read more about the flag in the [3.4 release notes](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-4.html#faster-subsequent-builds-with-the---incremental- flag). To control which folders you want to the files to be built to, use the config option `tsBuildInfoFile`. * Default: `true` if `composite`; `false` otherwise. * Related: * `composite` * `tsBuildInfoFile` * Released: [3.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-4.html) ### TS Build Info File - `tsBuildInfoFile` This setting lets you specify a file for storing incremental compilation information as a part of composite projects which enables faster building of larger TypeScript codebases. You can read more about composite projects [in the handbook](../docs/handbook/project-references). The default depends on a combination of other settings: * If `outFile` is set, the default is `.tsbuildinfo`. * If `rootDir` and `outDir` are set, then the file is `//.tsbuildinfo` For example, if `rootDir` is `src`, `outDir` is `dest`, and the config is `./tsconfig.json`, then the default is `./tsconfig.tsbuildinfo` as the relative path from `src/` to `./tsconfig.json` is `../`. * If `outDir` is set, then the default is `/.tsbuildInfo` * Otherwise, the default is `.tsbuildInfo` * Default: `.tsbuildinfo` * Related: * `incremental` * `composite` * Released: [3.4](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-4.html) ## Output Formatting ### No Error Truncation - `noErrorTruncation` Do not truncate error messages. With `false`, the default. var x: { propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; propertyWithAnExceedinglyLongName8: string; };   // String representation of type of 'x' should be truncated in error message var s: string = x; With `true` var x: { propertyWithAnExceedinglyLongName1: string; propertyWithAnExceedinglyLongName2: string; propertyWithAnExceedinglyLongName3: string; propertyWithAnExceedinglyLongName4: string; propertyWithAnExceedinglyLongName5: string; propertyWithAnExceedinglyLongName6: string; propertyWithAnExceedinglyLongName7: string; propertyWithAnExceedinglyLongName8: string; };   // String representation of type of 'x' should be truncated in error message var s: string = x; * Released: [1.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-0.html) ### Preserve Watch Output - `preserveWatchOutput` Whether to keep outdated console output in watch mode instead of clearing the screen every time a change happened. * Internal * Released: [2.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-8.html) ### Pretty - `pretty` Stylize errors and messages using color and context, this is on by default — offers you a chance to have less terse, single colored messages from the compiler. * Default: `true` * Released: [1.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-8.html) ## Completeness ### Skip Default Lib Check - `skipDefaultLibCheck` Use `skipLibCheck` instead. Skip type checking of default library declaration files. * Released: [1.6](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-1-6.html) ### Skip Lib Check - `skipLibCheck` Skip type checking of declaration files. This can save time during compilation at the expense of type-system accuracy. For example, two libraries could define two copies of the same `type` in an inconsistent way. Rather than doing a full check of all `d.ts` files, TypeScript will type check the code you specifically refer to in your app’s source code. A common case where you might think to use `skipLibCheck` is when there are two copies of a library’s types in your `node_modules`. In these cases, you should consider using a feature like [yarn’s resolutions](https://yarnpkg.com/lang/en/docs/selective-version-resolutions/) to ensure there is only one copy of that dependency in your tree or investigate how to ensure there is only one copy by understanding the dependency resolution to fix the issue without additional tooling. Another possibility is when you are migrating between TypeScript releases and the changes cause breakages in node_modules and the JS standard libraries which you do not want to deal with during the TypeScript update. Note, that if these issues come from the TypeScript standard library you can replace the library using [TypeScript 4.5’s lib replacement](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-5.html#supporting-lib-from-node_modules) technique. * Recommended * Released: [2.0](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-2-0.html) ## Command Line ## Watch Options TypeScript 3.8 shipped a new strategy for watching directories, which is crucial for efficiently picking up changes to `node_modules`. On operating systems like Linux, TypeScript installs directory watchers (as opposed to file watchers) on `node_modules` and many of its subdirectories to detect changes in dependencies. This is because the number of available file watchers is often eclipsed by the number of files in `node_modules`, whereas there are way fewer directories to track. Because every project might work better under different strategies, and this new approach might not work well for your workflows, TypeScript 3.8 introduces a new `watchOptions` field which allows users to tell the compiler/language service which watching strategies should be used to keep track of files and directories. ### Assume Changes Only Affect Direct Dependencies - `assumeChangesOnlyAffectDirectDependencies` When this option is enabled, TypeScript will avoid rechecking/rebuilding all truly possibly-affected files, and only recheck/rebuild files that have changed as well as files that directly import them. This can be considered a ‘fast & loose’ implementation of the watching algorithm, which can drastically reduce incremental rebuild times at the expense of having to run the full build occasionally to get all compiler error messages. * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ## Watch Options You can configure the how TypeScript `--watch` works. This section is mainly for handling case where `fs.watch` and `fs.watchFile` have additional constraints like on Linux. You can read more at [Configuring Watch](../docs/handbook/configuring-watch). ### Watch File - `watchFile` The strategy for how individual files are watched. * `fixedPollingInterval`: Check every file for changes several times a second at a fixed interval. * `priorityPollingInterval`: Check every file for changes several times a second, but use heuristics to check certain types of files less frequently than others. * `dynamicPriorityPolling`: Use a dynamic queue where less-frequently modified files will be checked less often. * `useFsEvents` (the default): Attempt to use the operating system/file system’s native events for file changes. * `useFsEventsOnParentDirectory`: Attempt to use the operating system/file system’s native events to listen for changes on a file’s parent directory * Allowed: * `fixedpollinginterval` * `prioritypollinginterval` * `dynamicprioritypolling` * `fixedchunksizepolling` * `usefsevents` * `usefseventsonparentdirectory` * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Watch Directory - `watchDirectory` The strategy for how entire directory trees are watched under systems that lack recursive file-watching functionality. * `fixedPollingInterval`: Check every directory for changes several times a second at a fixed interval. * `dynamicPriorityPolling`: Use a dynamic queue where less-frequently modified directories will be checked less often. * `useFsEvents` (the default): Attempt to use the operating system/file system’s native events for directory changes. * Allowed: * `usefsevents` * `fixedpollinginterval` * `dynamicprioritypolling` * `fixedchunksizepolling` * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Fallback Polling - `fallbackPolling` When using file system events, this option specifies the polling strategy that gets used when the system runs out of native file watchers and/or doesn’t support native file watchers. * `fixedPollingInterval`: Check every file for changes several times a second at a fixed interval. * `priorityPollingInterval`: Check every file for changes several times a second, but use heuristics to check certain types of files less frequently than others. * `dynamicPriorityPolling`: Use a dynamic queue where less-frequently modified files will be checked less often. * `synchronousWatchDirectory`: Disable deferred watching on directories. Deferred watching is useful when lots of file changes might occur at once (e.g. a change in `node_modules` from running `npm install`), but you might want to disable it with this flag for some less-common setups. * Allowed: * `fixedinterval` * `priorityinterval` * `dynamicpriority` * `fixedchunksize` * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Synchronous Watch Directory - `synchronousWatchDirectory` Synchronously call callbacks and update the state of directory watchers on platforms that don`t support recursive watching natively. Instead of giving a small timeout to allow for potentially multiple edits to occur on a file. { "watchOptions": { "synchronousWatchDirectory": true } } * Released: [3.8](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-3-8.html) ### Exclude Directories - `excludeDirectories` You can use `excludeFiles` to drastically reduce the number of files which are watched during `--watch`. This can be a useful way to reduce the number of open file which TypeScript tracks on Linux. { "watchOptions": { "excludeDirectories": ["**/node_modules", "_build", "temp/*"] } } * Released: [4.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-2.html) ### Exclude Files - `excludeFiles` You can use `excludeFiles` to remove a set of specific files from the files which are watched. { "watchOptions": { "excludeFiles": ["temp/file.ts"] } } * Released: [4.2](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-2.html) ## Type Acquisition Type Acquisition is only important for JavaScript projects. In TypeScript projects you need to include the types in your projects explicitly. However, for JavaScript projects, the TypeScript tooling will download types for your modules in the background and outside of your node_modules folder. ### Enable - `enable` Disables automatic type acquisition in JavaScript projects: { "typeAcquisition": { "enable": false } } ### Include - `include` If you have a JavaScript project where TypeScript needs additional guidance to understand global dependencies, or have disabled the built-in inference via `disableFilenameBasedTypeAcquisition`. You can use `include` to specify which types should be used from DefinitelyTyped: { "typeAcquisition": { "include": ["jquery"] } } ### Exclude - `exclude` Offers a config for disabling the type-acquisition for a certain module in JavaScript projects. This can be useful for projects which include other libraries in testing infrastructure which aren’t needed in the main application. { "typeAcquisition": { "exclude": ["jest", "mocha"] } } ### Disable Filename Based Type Acquisition - `disableFilenameBasedTypeAcquisition` TypeScript’s type acquisition can infer what types should be added based on filenames in a project. This means that having a file like `jquery.js` in your project would automatically download the types for JQuery from DefinitelyTyped. You can disable this via `disableFilenameBasedTypeAcquisition`. { "typeAcquisition": { "disableFilenameBasedTypeAcquisition": true } } * Released: [4.1](https://www.typescriptlang.org/docs/handbook/release- notes/typescript-4-1.html)