{
  "options": [
    {
      "id": "checkJs",
      "slug": "check-js",
      "title": "checkJs",
      "kind": "compilerOption",
      "option": "checkJs",
      "category": "Checking JavaScript",
      "tsCategory": "JavaScript Support",
      "type": "boolean",
      "default": "false",
      "flag": "--checkJs",
      "officialDescription": "Enable error reporting in type-checked JavaScript files.",
      "since": "2.3",
      "startWith": "`\"checkJs\": true`",
      "summary": "checkJs turns on TypeScript's error reporting for .js files. What it checks, how it relates to allowJs and // @ts-check, and how to switch it on.",
      "intro": [
        "`checkJs` is the option that makes TypeScript report errors in JavaScript files. With it on, `tsc` and your editor check every `.js` file in the project the way they check `.ts` files, using your JSDoc comments where you have written them and inference everywhere else.",
        "Every jsconfig.json on this site sets it. In TypeScript 5.9, `checkJs` also turns on `allowJs` when you leave `allowJs` out, so `\"checkJs\": true` on its own both includes your JavaScript files and checks them."
      ],
      "examples": [
        "config/check-js-on",
        "config/check-js-pragma"
      ],
      "sections": [
        {
          "id": "what-it-checks",
          "heading": "What it catches with no annotations",
          "body": [
            "The first example has no JSDoc in it at all, and the checker still finds the typo. Without annotations, `checkJs` reports what it can work out from literals, the standard library, and the `@types` packages you install:"
          ],
          "list": [
            "misspelled properties and methods, often with a \"Did you mean\" suggestion",
            "calls with too many arguments (in JavaScript, a parameter without a JSDoc type counts as optional, so calls with fewer arguments are allowed)",
            "wrong types going into functions that do have types, such as the DOM and Node.js APIs",
            "imports of files and exports that do not exist"
          ]
        },
        {
          "id": "allowjs-and-ts-check",
          "heading": "checkJs, allowJs and // @ts-check",
          "body": [
            "[`allowJs`](/config/allow-js/) lets JavaScript files into the program; `checkJs` decides whether their errors are reported. A config file named `jsconfig.json` already defaults `allowJs` to true, and in TypeScript 5.9 `checkJs` implies it as well, so most JavaScript projects only need `checkJs`.",
            "You can also opt in one file at a time. A [`// @ts-check`](/config/ts-check/) comment at the top of a file checks that file even when `checkJs` is off, which is how the second example works; [`// @ts-nocheck`](/config/ts-nocheck/) at the top of a file skips it when `checkJs` is on.",
            "For a single line, [`// @ts-expect-error`](/config/ts-expect-error/) silences the error on the next line and is itself reported (TS2578) once there is nothing left to silence. [`// @ts-ignore`](/config/ts-ignore/) silences the next line without that check, so it can hide a later, different error."
          ]
        },
        {
          "id": "existing-codebase",
          "heading": "Switching it on in an existing codebase",
          "body": [
            "In a large JavaScript codebase the first run can report hundreds of errors. A workable order: turn on `checkJs` without `strict`, fix or `// @ts-nocheck` the noisiest files, then turn on [`strict`](/config/strict/) (or [`noImplicitAny`](/config/no-implicit-any/) first) once the count is manageable. The relaxed level of the [jsconfig generator](/tools/jsconfig-generator/) is that first step."
          ]
        }
      ],
      "gotchas": [
        "Set [`noEmit`](/config/no-emit/) too. A config file named `tsconfig.json` with `allowJs` and no `outDir` makes `tsc` try to write output over your own `.js` files, which fails with TS5055 (\"Cannot write file … because it would overwrite input file\"). A file named `jsconfig.json` defaults `noEmit` to true.",
        "`checkJs` changes what `tsc` reports and nothing else. Node.js and browsers run the same JavaScript whether it is on or off.",
        "Without `checkJs` (and without `// @ts-check`), editors still give completions and hovers in `.js` files but show no type errors, which can look as if everything passes."
      ],
      "faq": [
        {
          "q": "Do I need both allowJs and checkJs?",
          "a": "Not in TypeScript 5.9: `checkJs` turns on `allowJs` when you leave `allowJs` out, and a file named `jsconfig.json` defaults `allowJs` to true anyway. Setting both does no harm and makes the intent plain to the next reader."
        },
        {
          "q": "Is checkJs the same as // @ts-check?",
          "a": "They turn on the same checks. `checkJs` applies to every JavaScript file in the project; `// @ts-check` applies to the one file it is written in, and works even when `checkJs` is off."
        }
      ],
      "related": [
        "config/allow-js",
        "config/ts-check",
        "config/strict",
        "errors/ts7006",
        "start/node-esm",
        "tools/jsconfig-generator"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: checkJs",
          "url": "https://www.typescriptlang.org/tsconfig/#checkJs",
          "publisher": "TypeScript"
        },
        {
          "title": "TSConfig Reference: allowJs",
          "url": "https://www.typescriptlang.org/tsconfig/#allowJs",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.3 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Type Checking JavaScript Files",
          "url": "https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "jsconfig.json",
          "url": "https://code.visualstudio.com/docs/languages/jsconfig",
          "publisher": "Visual Studio Code docs"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "allowJs",
      "slug": "allow-js",
      "title": "allowJs",
      "kind": "compilerOption",
      "option": "allowJs",
      "category": "Checking JavaScript",
      "tsCategory": "JavaScript Support",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `checkJs` is on and `allowJs` is left out)",
      "jsconfigDefault": "true",
      "flag": "--allowJs",
      "officialDescription": "Allow JavaScript files to be a part of your program. Use the 'checkJs' option to get errors from these files.",
      "since": "1.8",
      "startWith": "Nothing in a `jsconfig.json`, where it is already on. In a `tsconfig.json`, write `\"allowJs\": true` (or let `\"checkJs\": true` imply it)",
      "summary": "allowJs brings .js files into the program so their types reach other files, without reporting errors in them. How it differs from checkJs.",
      "intro": [
        "`allowJs` lets JavaScript files into the program. `tsc` reads them, works out the types of what they export (from JSDoc where there is some, by inference elsewhere), and lets other files use those types. It does not report errors inside them: that is [`checkJs`](/config/check-js/).",
        "A file named `jsconfig.json` turns `allowJs` on by default, and in TypeScript 5.9 `checkJs` turns it on when you leave it out. In a JavaScript project you rarely write it; it matters in a `tsconfig.json`, and in projects that mix `.ts` and `.js` files."
      ],
      "examples": [
        "config/allow-js-unchecked-file"
      ],
      "sections": [
        {
          "id": "in-the-program-not-checked",
          "heading": "In the program, but not checked",
          "body": [
            "The example shows the difference in one project. `legacy.js` opts out of checking with [`// @ts-nocheck`](/config/ts-nocheck/), so it is in the program the way `allowJs` alone puts a file there: its JSDoc still types `orderTotal`, and the call in `checkout.js` that passes a string price is an error. The misspelled `toUppercase` inside `legacy.js` is never reported, because nothing checks that file.",
            "That is the whole job of `allowJs`: types flow out of JavaScript files. Turning on `checkJs`, or adding `// @ts-check` to one file, is what makes their own mistakes visible."
          ]
        },
        {
          "id": "when-to-write-it",
          "heading": "When you need to write it",
          "body": [
            "Three cases, all outside a plain `jsconfig.json`:"
          ],
          "list": [
            "a config file named `tsconfig.json` for a JavaScript project: write `\"checkJs\": true` (which implies `allowJs` in TypeScript 5.9) or both",
            "a TypeScript project with some `.js` files left in it: `\"allowJs\": true` with `checkJs` off lets `.ts` files import them, and `// @ts-check` opts single files in as you convert them",
            "a project that writes output from `.js` files (Babel-free downlevel builds, or [`.d.ts` files for a package](/config/declaration/)): `allowJs` is what lets those files be inputs"
          ]
        }
      ],
      "gotchas": [
        "With `allowJs` and output turned on, `tsc` writes `.js` files. Without `outDir` or [`noEmit`](/config/no-emit/), it would write over your sources, so it stops with TS5055 instead.",
        "JavaScript files inside `node_modules` are a separate setting: [`maxNodeModuleJsDepth`](/config/max-node-module-js-depth/) decides whether TypeScript reads them.",
        "Setting `\"allowJs\": false` while `\"checkJs\": true` is a config error in TypeScript 5.9 (TS5052): checking JavaScript needs JavaScript in the program."
      ],
      "faq": [
        {
          "q": "Does allowJs check my JavaScript?",
          "a": "No. It makes `.js` files part of the program so their types are known. Errors inside them are reported only with `checkJs` on, or in a file that starts with `// @ts-check`."
        }
      ],
      "related": [
        "config/check-js",
        "config/max-node-module-js-depth",
        "config/no-emit",
        "config/ts-nocheck"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: allowJs",
          "url": "https://www.typescriptlang.org/tsconfig/#allowJs",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 1.8 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Type Checking JavaScript Files",
          "url": "https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "maxNodeModuleJsDepth",
      "slug": "max-node-module-js-depth",
      "title": "maxNodeModuleJsDepth",
      "kind": "compilerOption",
      "option": "maxNodeModuleJsDepth",
      "category": "Checking JavaScript",
      "tsCategory": "JavaScript Support",
      "type": "number",
      "default": "0",
      "jsconfigDefault": "2",
      "flag": "--maxNodeModuleJsDepth",
      "officialDescription": "Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'.",
      "since": null,
      "startWith": "Keep the `jsconfig.json` default, `2`. Write `0` if reading JavaScript packages makes checking slow",
      "summary": "maxNodeModuleJsDepth sets whether TypeScript reads JavaScript packages in node_modules for types. jsconfig.json defaults it to 2, tsconfig.json to 0.",
      "intro": [
        "When a package in `node_modules` ships only JavaScript, with no `.d.ts` files and no `@types` package, TypeScript can read its `.js` files to work out its types, JSDoc included. `maxNodeModuleJsDepth` sets how far it goes: `0` reads none of them, `2` reads the file your import resolves to and the JavaScript files it imports in turn, two levels deep.",
        "A file named `jsconfig.json` defaults it to `2`; a `tsconfig.json` defaults it to `0`. At `0`, importing such a package gives you `any`, and under [`noImplicitAny`](/config/no-implicit-any/) the import itself is an error (TS7016)."
      ],
      "examples": [
        "config/max-node-module-js-depth-0",
        "config/max-node-module-js-depth-2"
      ],
      "sections": [
        {
          "id": "what-the-examples-show",
          "heading": "What the two examples show",
          "body": [
            "Both examples import the same small JavaScript-only package, `slugify-lite`, whose function has a JSDoc `@param {string}`. At depth `0`, TypeScript does not look inside the package: the import is TS7016 and `slugify` is `any`, so the wrong argument passes unnoticed. At the `jsconfig.json` default of `2`, TypeScript reads the package, picks up the JSDoc, and reports `slugify(42)`.",
            "The package also contains a mistake of its own, `words.lenght`. Neither example reports it: files read from `node_modules` this way lend their types to your code, but type errors inside them are not reported.",
            "One thing from inside a package can still show up. If the package imports another JavaScript package that lies past the depth limit, that import is reported as TS7016 in the package's own file, with a path into `node_modules`. Raising the depth by one, or installing types for the inner package, makes it go away."
          ]
        },
        {
          "id": "packages-with-types",
          "heading": "Packages that ship types are not affected",
          "body": [
            "When a package has a `types` entry, a `.d.ts` file next to its JavaScript, or an `@types` package, TypeScript uses that and this option changes nothing. It only matters for packages that are JavaScript all the way down."
          ]
        },
        {
          "id": "when-to-lower-it",
          "heading": "When to set it to 0",
          "body": [
            "Reading large JavaScript packages takes time, and inferred types from code that was never written for a checker can be loose or odd. If checking is slow or a dependency's inferred types get in the way, set `0` and give the package types another way: install its `@types` package, or write a one-line declaration such as `declare module \"slugify-lite\";` in a `.d.ts` file, which types it as `any` on purpose."
          ]
        }
      ],
      "gotchas": [
        "The depth counts import steps, not folders or packages: depth `1` reads the file your import resolves to, and `2` also reads the JavaScript files that file imports, in the same package or another one.",
        "The option only applies when JavaScript files are allowed in the program ([`allowJs`](/config/allow-js/), which a `jsconfig.json` and `checkJs` both give you)."
      ],
      "faq": [
        {
          "q": "Why does the same import work in my editor but fail with tsc?",
          "a": "Check the config file name. A `jsconfig.json` reads JavaScript packages two levels deep by default, a `tsconfig.json` does not, so the same import can be typed in one project and TS7016 in the other."
        }
      ],
      "related": [
        "config/allow-js",
        "config/skip-lib-check",
        "config/no-implicit-any",
        "tags/import",
        "errors/ts7016"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: maxNodeModuleJsDepth",
          "url": "https://www.typescriptlang.org/tsconfig/#maxNodeModuleJsDepth",
          "publisher": "TypeScript"
        },
        {
          "title": "jsconfig.json",
          "url": "https://code.visualstudio.com/docs/languages/jsconfig",
          "publisher": "Visual Studio Code docs"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "noEmit",
      "slug": "no-emit",
      "title": "noEmit",
      "kind": "compilerOption",
      "option": "noEmit",
      "category": "Checking JavaScript",
      "tsCategory": "Emit",
      "type": "boolean",
      "default": "false",
      "jsconfigDefault": "true",
      "flag": "--noEmit",
      "officialDescription": "Disable emitting files from a compilation.",
      "since": null,
      "startWith": "`\"noEmit\": true` (already the default in a `jsconfig.json`; write it anyway so the file says what it does)",
      "summary": "noEmit makes tsc check your files and write nothing. A jsconfig.json defaults it to true; a tsconfig.json with allowJs needs it, or tsc stops with TS5055.",
      "intro": [
        "By default `tsc` checks your files and then writes output: `.js` files, and `.d.ts` files if you ask. In a JavaScript project your source already is the output, so all you want is the checking. `noEmit` turns the writing off.",
        "A file named `jsconfig.json` defaults `noEmit` to `true`. A `tsconfig.json` does not: with `allowJs` and no `outDir`, `tsc` would write each `.js` file over itself, so it stops with TS5055 for every file instead."
      ],
      "examples": [],
      "sections": [
        {
          "id": "ts5055",
          "heading": "The error without it",
          "body": [
            "This is what `tsc` prints for a `tsconfig.json` that sets `allowJs` (or `checkJs`) and neither `noEmit` nor `outDir`. The path is your own file; the message is the same in every project:"
          ],
          "snippets": [
            {
              "lang": "sh",
              "code": "$ npx tsc -p tsconfig.json\nerror TS5055: Cannot write file '/home/ada/shop/src/cart.js' because it would overwrite input file."
            }
          ]
        },
        {
          "id": "publishing-types",
          "heading": "When you do want output: .d.ts files",
          "body": [
            "A package written in JavaScript can still ship types: [`declaration` with `emitDeclarationOnly`](/config/declaration/) writes `.d.ts` files and never touches your `.js`. Keep that in a second config file, so the everyday `jsconfig.json` stays a pure check with `noEmit`.",
            "If that second config `extends` your `jsconfig.json`, it inherits `noEmit: true`, the `jsconfig.json` default, even when the file never writes it. Set `\"noEmit\": false` in the second config, or `tsc` writes nothing and says nothing."
          ]
        }
      ],
      "gotchas": [
        "`noEmit` silently wins over `emitDeclarationOnly`: TypeScript 5.9 reports no error for the pair, and no file is written.",
        "`noEmit` skips the writing, not any of the checking: the same errors are reported either way. For a faster run, see [`skipLibCheck`](/config/skip-lib-check/)."
      ],
      "faq": [
        {
          "q": "Does noEmit change how my code runs?",
          "a": "No. With `noEmit` nothing is written, so what runs is exactly the JavaScript you wrote. Without it, tsc writes output files, and only those can differ from the code you wrote."
        }
      ],
      "related": [
        "config/declaration",
        "config/allow-js",
        "config/check-js",
        "start/node-esm"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: noEmit",
          "url": "https://www.typescriptlang.org/tsconfig/#noEmit",
          "publisher": "TypeScript"
        },
        {
          "title": "jsconfig.json",
          "url": "https://code.visualstudio.com/docs/languages/jsconfig",
          "publisher": "Visual Studio Code docs"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "declaration",
      "slug": "declaration",
      "title": "declaration and emitDeclarationOnly",
      "kind": "compilerOption",
      "option": "declaration",
      "alsoCovers": [
        "emitDeclarationOnly",
        "declarationMap",
        "declarationDir"
      ],
      "category": "Checking JavaScript",
      "tsCategory": "Emit",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `composite` is on)",
      "flag": "--declaration",
      "officialDescription": "Generate .d.ts files from TypeScript and JavaScript files in your project.",
      "since": "3.7",
      "startWith": "In a second config used for publishing: `\"declaration\": true` with `\"emitDeclarationOnly\": true` and a `declarationDir`",
      "summary": "declaration and emitDeclarationOnly make tsc write .d.ts files from your JavaScript and its JSDoc, so a package written in JavaScript ships its own types.",
      "intro": [
        "Since TypeScript 3.7, `tsc` can write declaration (`.d.ts`) files from JavaScript. Turn on `declaration` to write them, `emitDeclarationOnly` so that `tsc` writes only those and never a `.js` file, and `declarationDir` to put them in a folder of their own.",
        "The `.d.ts` files carry your JSDoc types in TypeScript syntax. Publish them with your package, point `package.json` at them, and anyone who installs the package gets your types in their editor and their `tsc`, whether they write TypeScript or checked JavaScript."
      ],
      "examples": [
        "config/declaration-emit",
        "config/declaration-emit#types/geometry.d.ts"
      ],
      "sections": [
        {
          "id": "second-config",
          "heading": "A second config for the .d.ts files",
          "body": [
            "Your `jsconfig.json` keeps `noEmit` and stays the file your editor and `npm run lint` use. A second file extends it and turns writing on, for declarations only. The second example above is the file `tsc -p jsconfig.types.json` wrote from the first; this site runs that config again on every build, in memory, and the build fails if the output no longer matches the file shown."
          ],
          "snippets": [
            {
              "file": "jsconfig.types.json",
              "from": "config/declaration-emit",
              "lang": "json",
              "code": "{\n  \"extends\": \"./jsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": false,\n    \"declaration\": true,\n    \"emitDeclarationOnly\": true,\n    \"declarationDir\": \"types\"\n  }\n}"
            },
            {
              "lang": "sh",
              "code": "npx tsc -p jsconfig.types.json"
            }
          ]
        },
        {
          "id": "what-tsc-writes",
          "heading": "What tsc writes",
          "body": [
            "Compare the two examples:"
          ],
          "list": [
            "a `@typedef` becomes an exported `type`, so users of the package can import `Point` by name",
            "parameter and return types come from the JSDoc, or from inference where there is none (`distance` returns `number` without a `@returns` tag)",
            "class properties assigned in the constructor become declared properties",
            "an exported object literal (`origin`) is written as a `namespace` with one variable per property, which works the same for importers",
            "the JSDoc comments are copied into the `.d.ts`, so hovers in the user's editor show your descriptions"
          ]
        },
        {
          "id": "declaration-dir-and-map",
          "heading": "declarationDir and declarationMap",
          "body": [
            "`declarationDir` sends the `.d.ts` files to their own folder (here `types/`), which keeps them apart from your sources and easy to leave out of git. `declarationMap` also writes a `.d.ts.map` beside each file; with it, an editor's \"go to definition\" in a project that uses your package can land in your `.js` source instead of the `.d.ts`, provided the source files are published too."
          ]
        },
        {
          "id": "package-json",
          "heading": "Pointing package.json at the types",
          "body": [
            "TypeScript finds a package's types through its `package.json`. With an `exports` field, put a `types` condition first in each entry; TypeScript's 4.7 release notes say it should always come first."
          ],
          "snippets": [
            {
              "file": "package.json",
              "from": "config/declaration-emit",
              "lang": "json",
              "code": "{\n  \"type\": \"module\",\n  \"exports\": {\n    \".\": {\n      \"types\": \"./types/geometry.d.ts\",\n      \"default\": \"./src/geometry.js\"\n    }\n  },\n  \"files\": [\"src\", \"types\"]\n}"
            }
          ]
        }
      ],
      "gotchas": [
        "A second config that `extends` a `jsconfig.json` inherits `noEmit: true` even though the base file never writes it, and `noEmit` quietly wins: nothing is written and nothing is reported. Set `\"noEmit\": false` explicitly.",
        "`emitDeclarationOnly` needs `declaration` (or `composite`) on; on its own it is a config error.",
        "Types you never wrote down can surprise you: an untyped parameter becomes `any` in the `.d.ts`. Check the output before you publish it."
      ],
      "faq": [
        {
          "q": "Should the .d.ts files be committed to git?",
          "a": "Either works. Many packages write them just before publishing (an npm `prepack` script that runs `tsc -p jsconfig.types.json`) and keep the folder out of git, so the files can never be stale."
        }
      ],
      "related": [
        "start/library",
        "config/no-emit",
        "tags/typedef",
        "tags/import"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: declaration",
          "url": "https://www.typescriptlang.org/tsconfig/#declaration",
          "publisher": "TypeScript"
        },
        {
          "title": "TSConfig Reference: emitDeclarationOnly",
          "url": "https://www.typescriptlang.org/tsconfig/#emitDeclarationOnly",
          "publisher": "TypeScript"
        },
        {
          "title": "TSConfig Reference: declarationDir",
          "url": "https://www.typescriptlang.org/tsconfig/#declarationDir",
          "publisher": "TypeScript"
        },
        {
          "title": "TSConfig Reference: declarationMap",
          "url": "https://www.typescriptlang.org/tsconfig/#declarationMap",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 3.7 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 2.8 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 4.7 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Creating .d.ts Files from .js files",
          "url": "https://www.typescriptlang.org/docs/handbook/declaration-files/dts-from-js.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "skipLibCheck",
      "slug": "skip-lib-check",
      "title": "skipLibCheck",
      "kind": "compilerOption",
      "option": "skipLibCheck",
      "category": "Checking JavaScript",
      "tsCategory": "Completeness",
      "type": "boolean",
      "default": "false",
      "jsconfigDefault": "true",
      "flag": "--skipLibCheck",
      "officialDescription": "Skip type checking all .d.ts files.",
      "since": "2.0",
      "startWith": "`\"skipLibCheck\": true` (the `jsconfig.json` default), and turn it off now and then if you write `.d.ts` files of your own",
      "summary": "skipLibCheck skips checking every .d.ts file, your own included. A jsconfig.json turns it on by default, which can hide a typo in a .d.ts you wrote.",
      "intro": [
        "Every `.d.ts` file in the program is normally checked along with your code: the ones in `node_modules`, and any you write yourself. `skipLibCheck` skips checking all of them. Their types are still read and used; only errors inside the `.d.ts` files go unreported.",
        "A file named `jsconfig.json` turns it on by default, which saves time and spares you errors in dependencies that you cannot fix. The cost shows up when you write a `.d.ts` of your own: a mistake in it is skipped too."
      ],
      "examples": [
        "config/skip-lib-check-off",
        "config/skip-lib-check-on"
      ],
      "sections": [
        {
          "id": "your-own-dts",
          "heading": "Your own .d.ts files are skipped too",
          "body": [
            "The examples declare a global in `globals.d.ts` and misspell its type. With `skipLibCheck` off, `tsc` reports `Dat`; with it on, the typo goes through, `BUILD_DATE` quietly becomes `any`, and `BUILD_DATE.getFullYear()` in `main.js` is not checked at all.",
            "If your project has `.d.ts` files of its own (globals, `declare module` blocks for untyped packages, CSS module types), run `tsc -p jsconfig.json --skipLibCheck false` from time to time, or in CI, to check them."
          ]
        },
        {
          "id": "dependencies",
          "heading": "Why skipping dependencies is usually right",
          "body": [
            "Errors inside `node_modules/**/*.d.ts` usually come from two packages that declare the same global differently, or a types package written for a newer TypeScript. You cannot fix them in your project, and they say nothing about your code. Skipping them also makes every run faster."
          ]
        }
      ],
      "gotchas": [
        "Your `.js` files are always checked in full; `skipLibCheck` only concerns `.d.ts` files.",
        "A `.d.ts` file that TypeScript writes for you (see [`declaration`](/config/declaration/)) is output, not input, so this option does not apply to it."
      ],
      "faq": [
        {
          "q": "Is skipLibCheck safe to turn on?",
          "a": "For dependencies, yes; it is the default in a `jsconfig.json` and in the config `tsc --init` writes in TypeScript 5.9. The one risk is your own `.d.ts` files, which are skipped as well."
        }
      ],
      "related": [
        "config/allow-arbitrary-extensions",
        "config/max-node-module-js-depth",
        "config/declaration",
        "config/check-js"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: skipLibCheck",
          "url": "https://www.typescriptlang.org/tsconfig/#skipLibCheck",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "resolveJsonModule",
      "slug": "resolve-json-module",
      "title": "resolveJsonModule",
      "kind": "compilerOption",
      "option": "resolveJsonModule",
      "category": "Checking JavaScript",
      "tsCategory": "Modules",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `module` is `nodenext`, `node20` or `preserve`, or `moduleResolution` is `bundler`)",
      "flag": "--resolveJsonModule",
      "officialDescription": "Enable importing .json files.",
      "since": "2.9",
      "startWith": "Usually nothing: `nodenext` and `bundler` turn it on. With other `module` settings, write `\"resolveJsonModule\": true`",
      "summary": "resolveJsonModule lets you import .json files and types their contents. nodenext and bundler turn it on; ES modules still need the json import attribute.",
      "intro": [
        "`resolveJsonModule` lets an `import` (or `require`) of a `.json` file resolve, and gives the result the type of the file's contents: `{ \"port\": 8080 }` becomes `{ port: number }`. A typo in a property name is then an error like any other.",
        "In TypeScript 5.9 it is on by default when `module` is `nodenext`, `node20` or `preserve`, or when `moduleResolution` is `bundler`, which covers the setups on this site. With `module` set to `node16`, `node18` or an `es` version alone, write it yourself."
      ],
      "examples": [
        "config/resolve-json-module-nodenext",
        "config/resolve-json-module-off"
      ],
      "sections": [
        {
          "id": "import-attribute",
          "heading": "ES modules need the json import attribute",
          "body": [
            "Node.js loads a JSON file from an ES module only with an import attribute: `import config from \"./config.json\" with { type: \"json\" };`. Under `module: \"nodenext\"`, the checker holds you to it and reports a JSON import without one ([TS1543](/errors/ts1543/)). CommonJS files load JSON with `require(\"./config.json\")` and need no attribute."
          ],
          "examples": [
            "config/resolve-json-module-attribute"
          ]
        },
        {
          "id": "json-types",
          "heading": "What type a JSON import gets",
          "body": [
            "TypeScript reads the file and widens the values: strings become `string`, numbers `number`, arrays of mixed values a union. It does not keep literal values, so `\"port\": 8080` is `number`, not `8080`. To type a config more precisely, annotate the import's use with a `@type` or check it with [`@satisfies`](/tags/satisfies/)."
          ]
        }
      ],
      "gotchas": [
        "A big JSON file is read and typed on every check. For large data files that you import, a JSDoc `@type` on a value read with `fs` can be faster.",
        "The typed JSON is the file as it is on disk when you check. A JSON file that changes at deploy time can differ from what was checked."
      ],
      "faq": [
        {
          "q": "Why do I get TS2732 for a JSON import?",
          "a": "Your `module` and `moduleResolution` do not turn `resolveJsonModule` on (for example `module: \"node18\"`, or a `bundler` setup that sets it to `false`). Add `\"resolveJsonModule\": true`."
        }
      ],
      "related": [
        "config/module",
        "tags/type",
        "tags/satisfies",
        "start/node-esm"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: resolveJsonModule",
          "url": "https://www.typescriptlang.org/tsconfig/#resolveJsonModule",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.9 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Modules: ECMAScript modules, JSON modules",
          "url": "https://nodejs.org/api/esm.html#json-modules",
          "publisher": "Node.js docs"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "allowArbitraryExtensions",
      "slug": "allow-arbitrary-extensions",
      "title": "allowArbitraryExtensions",
      "kind": "compilerOption",
      "option": "allowArbitraryExtensions",
      "category": "Checking JavaScript",
      "tsCategory": "Modules",
      "type": "boolean",
      "default": "false",
      "flag": "--allowArbitraryExtensions",
      "officialDescription": "Enable importing files with any extension, provided a declaration file is present.",
      "since": "5.0",
      "startWith": "`\"allowArbitraryExtensions\": true` when you import CSS, SVG or other non-JavaScript files and write a declaration file for each",
      "summary": "allowArbitraryExtensions lets a .css or other non-JavaScript import use a declaration file such as theme.d.css.ts. Without it, that import is TS6263.",
      "intro": [
        "Browsers and bundlers can import files that are not JavaScript: CSS module scripts, JSON, SVG and more. TypeScript cannot read those files, but it can read a declaration file that describes one. For `./theme.css`, that file is named `theme.d.css.ts`, and `allowArbitraryExtensions` is the option that lets TypeScript use it.",
        "Without the option, TypeScript finds the declaration file and still refuses the import, with TS6263. The option arrived with TypeScript 5.0."
      ],
      "examples": [
        "config/allow-arbitrary-extensions-off",
        "config/allow-arbitrary-extensions-on"
      ],
      "sections": [
        {
          "id": "naming",
          "heading": "Naming the declaration file",
          "body": [
            "Put `.d` before the file's own extension and `.ts` after it: `theme.css` → `theme.d.css.ts`, `logo.svg` → `logo.d.svg.ts`. The file describes what the import gives you; for a CSS module script that is one `CSSStyleSheet` as the default export."
          ]
        },
        {
          "id": "css-module-scripts",
          "heading": "CSS module scripts in the browser",
          "body": [
            "The examples use a CSS module script, a web platform feature: `import sheet from \"./theme.css\" with { type: \"css\" }` gives you a `CSSStyleSheet` to adopt into the document or a shadow root. Browser support is still uneven, so check MDN before relying on it without a bundler."
          ]
        },
        {
          "id": "wildcard",
          "heading": "One declaration for every file of a kind",
          "body": [
            "The other way to type such imports needs no option: a `.d.ts` file with `declare module \"*.css\" { … }` covers every CSS import at once. Use it when all imports of a kind look the same; use per-file declarations with `allowArbitraryExtensions` when each file exports something different (CSS modules with class names, for example)."
          ]
        }
      ],
      "gotchas": [
        "An import that binds nothing, such as `import \"./theme.css\"`, is not checked at all unless [`noUncheckedSideEffectImports`](/config/no-unchecked-side-effect-imports/) is on.",
        "Declaration files you write are skipped by [`skipLibCheck`](/config/skip-lib-check/), the `jsconfig.json` default, so a mistake in `theme.d.css.ts` goes unreported."
      ],
      "related": [
        "config/no-unchecked-side-effect-imports",
        "config/skip-lib-check",
        "config/resolve-json-module"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: allowArbitraryExtensions",
          "url": "https://www.typescriptlang.org/tsconfig/#allowArbitraryExtensions",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 5.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "import attributes (with)",
          "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import/with",
          "publisher": "MDN"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "strict",
      "slug": "strict",
      "title": "strict",
      "kind": "compilerOption",
      "option": "strict",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "ts6Default": "`true` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--strict",
      "officialDescription": "Enable all strict type-checking options.",
      "since": "2.3",
      "startWith": "`\"strict\": true` for new code; on an existing codebase, start without it and turn it on once the first errors are fixed",
      "summary": "strict turns on the strict type-checking family with one switch: nine options in TypeScript 5.9. What each catches in a .js file, and how to turn one back off.",
      "intro": [
        "`strict` is a shorthand. It turns on a family of checks that can each be set on their own: in TypeScript 5.9 that is `noImplicitAny`, `strictNullChecks`, `strictFunctionTypes`, `strictBindCallApply`, `strictPropertyInitialization`, `strictBuiltinIteratorReturn`, `noImplicitThis`, `useUnknownInCatchVariables` and `alwaysStrict`.",
        "In a JavaScript project the two that change the most are [`noImplicitAny`](/config/no-implicit-any/), which makes every untyped parameter an error (TS7006), and [`strictNullChecks`](/config/strict-null-checks/), which makes you handle `null` and `undefined`. TypeScript 6.0 makes `strict` the default, so write it either way to keep a config meaning the same thing across versions."
      ],
      "examples": [
        "config/strict-on",
        "config/strict-off"
      ],
      "sections": [
        {
          "id": "the-family",
          "heading": "What strict turns on",
          "body": [
            "Each member except `strictBuiltinIteratorReturn` has its own page with the same code checked both ways:"
          ],
          "list": [
            "[`noImplicitAny`](/config/no-implicit-any/): parameters and values that could only be `any`",
            "[`strictNullChecks`](/config/strict-null-checks/): `null` and `undefined` as their own types",
            "[`strictFunctionTypes`](/config/strict-function-types/): parameter types checked when one function type is assigned to another",
            "[`strictBindCallApply`](/config/strict-bind-call-apply/): arguments passed through `bind`, `call` and `apply`",
            "[`strictPropertyInitialization`](/config/strict-property-initialization/): class fields that are typed but never set",
            "[`noImplicitThis`](/config/no-implicit-this/): `this` with no known type",
            "[`useUnknownInCatchVariables`](/config/use-unknown-in-catch-variables/): `catch (err)` as `unknown`",
            "[`alwaysStrict`](/config/always-strict/): every file parsed in strict mode",
            "`strictBuiltinIteratorReturn` (TypeScript 5.6): the value a finished built-in iterator returns is `undefined`, not `any`"
          ]
        },
        {
          "id": "turning-one-off",
          "heading": "Turning one check back off",
          "body": [
            "An option you set yourself wins over `strict`. `\"strict\": true` with `\"strictPropertyInitialization\": false` keeps every strict check except that one. That is a reasonable middle step for a codebase with many classes, and the order you list them in does not matter."
          ],
          "snippets": [
            {
              "file": "jsconfig.json",
              "lang": "jsonc",
              "code": "{\n  \"compilerOptions\": {\n    \"checkJs\": true,\n    \"noEmit\": true,\n    \"strict\": true,\n    // every strict check except this one\n    \"strictPropertyInitialization\": false\n  }\n}"
            }
          ]
        },
        {
          "id": "upgrades",
          "heading": "The family grows",
          "body": [
            "New TypeScript releases add checks to `strict`: `useUnknownInCatchVariables` joined in 4.4 and `strictBuiltinIteratorReturn` in 5.6. Upgrading TypeScript can therefore report errors in code that passed before, without any change to your config. Read the release notes of each minor version before you move to it."
          ]
        },
        {
          "id": "not-in-strict",
          "heading": "Stricter options that strict leaves off",
          "body": [
            "These are not part of `strict` and are worth considering once it passes: [`noUncheckedIndexedAccess`](/config/no-unchecked-indexed-access/), [`exactOptionalPropertyTypes`](/config/exact-optional-property-types/), [`noImplicitReturns`](/config/no-implicit-returns/), [`noFallthroughCasesInSwitch`](/config/no-fallthrough-cases-in-switch/), [`noImplicitOverride`](/config/no-implicit-override/), [`noUnusedLocals` and `noUnusedParameters`](/config/no-unused-locals/), [`noPropertyAccessFromIndexSignature`](/config/no-property-access-from-index-signature/) and [`noUncheckedSideEffectImports`](/config/no-unchecked-side-effect-imports/). The strict level of the [jsconfig generator](/tools/jsconfig-generator/) adds the first four."
          ]
        }
      ],
      "gotchas": [
        "Without `strict`, a `.js` file is checked loosely: untyped parameters are `any` without complaint and `null` fits any type. Code can pass `npm run lint` and still fail on the first `undefined`.",
        "A config with no `strict` line means `false` in TypeScript 5.9 and `true` in 6.0. Write the line."
      ],
      "faq": [
        {
          "q": "Should I turn on strict in an existing JavaScript project?",
          "a": "Eventually. Start with `checkJs` alone, fix what it finds, then turn on `strict` (or `noImplicitAny` first, since it reports the most). The [checkJs page](/config/check-js/) describes the order."
        },
        {
          "q": "Is strict on by default?",
          "a": "Not in TypeScript 5.9, where it defaults to `false`. TypeScript 6.0 changes the default to `true`."
        }
      ],
      "related": [
        "config/no-implicit-any",
        "config/strict-null-checks",
        "config/check-js",
        "errors/ts7006",
        "tools/jsconfig-generator"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: strict",
          "url": "https://www.typescriptlang.org/tsconfig/#strict",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.3 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 4.4 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.6 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 6.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "noImplicitAny",
      "slug": "no-implicit-any",
      "title": "noImplicitAny",
      "kind": "compilerOption",
      "option": "noImplicitAny",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `strict` is on)",
      "ts6Default": "`true`, through `strict` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--noImplicitAny",
      "officialDescription": "Enable error reporting for expressions and declarations with an implied 'any' type.",
      "since": null,
      "startWith": "Leave it to [`strict`](/config/strict/), or write `\"noImplicitAny\": true` on its own as the first step on an existing codebase",
      "summary": "noImplicitAny reports values TypeScript can only type as any. In a .js file, that is mostly parameters with no JSDoc type and no default (TS7006).",
      "intro": [
        "When TypeScript cannot tell a value's type and has nothing to infer it from, it gives up with `any`, which turns checking off for that value. `noImplicitAny` makes that an error instead. In a JavaScript file the usual case is a function parameter without a JSDoc type, reported as [TS7006](/errors/ts7006/).",
        "It is part of [`strict`](/config/strict/) and reports more in a typical JavaScript codebase than any other member of the family, which makes it a good first step on its own."
      ],
      "examples": [
        "config/no-implicit-any-on",
        "config/no-implicit-any-off"
      ],
      "sections": [
        {
          "id": "what-it-reports",
          "heading": "What it reports in a .js file",
          "body": [
            "The common ones:"
          ],
          "list": [
            "a parameter with no `@param` type and no default value (TS7006), including callback parameters when the array they come from is itself untyped, as in the example",
            "a destructured parameter with no type (TS7031)",
            "an import of a JavaScript package with no types (TS7016); see [`maxNodeModuleJsDepth`](/config/max-node-module-js-depth/)"
          ]
        },
        {
          "id": "what-it-does-not",
          "heading": "Variables that start empty",
          "body": [
            "A variable that starts as `null`, `undefined` or `[]` is not left silently `any` under `strict`: TypeScript 5.9 follows what is assigned to it. Reading `a.length` after `let a = null` is [TS18047](/errors/ts18047/), and an empty array the checker cannot follow, because a closure captures it, is [TS7034](/errors/ts7034/). With `strict` off, such variables are `any`. Annotate them with `@type` when the type matters, for example `/** @type {string[]} */ const names = [];`."
          ]
        }
      ],
      "gotchas": [
        "A parameter with a default value is typed from the default (`function f(n = 0)` makes `n` a `number`), so it is not reported.",
        "An explicit `{any}` in JSDoc is not \"implicit\" and is never reported; it is a deliberate opt-out."
      ],
      "faq": [
        {
          "q": "Do I have to type every parameter?",
          "a": "Every parameter TypeScript cannot type from context. Callbacks passed to typed functions (`[1, 2].map((n) => n * 2)`) get their types from the function they are passed to and need no JSDoc."
        }
      ],
      "related": [
        "config/strict",
        "tags/param",
        "errors/ts7006",
        "errors/ts7053",
        "errors/ts7031",
        "errors/ts7034"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: noImplicitAny",
          "url": "https://www.typescriptlang.org/tsconfig/#noImplicitAny",
          "publisher": "TypeScript"
        },
        {
          "title": "Type Checking JavaScript Files",
          "url": "https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "strictNullChecks",
      "slug": "strict-null-checks",
      "title": "strictNullChecks",
      "kind": "compilerOption",
      "option": "strictNullChecks",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `strict` is on)",
      "ts6Default": "`true`, through `strict` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--strictNullChecks",
      "officialDescription": "When type checking, take into account 'null' and 'undefined'.",
      "since": "2.0",
      "startWith": "Leave it to [`strict`](/config/strict/); write `\"strictNullChecks\": false` only to turn this one check back off",
      "summary": "strictNullChecks makes null and undefined types of their own, so a value that may be missing is checked before use. It reports TS18047 and TS18048.",
      "intro": [
        "Without `strictNullChecks`, `null` and `undefined` fit every type, so a value that may be missing looks like it is always there. With it on, they are types of their own: `Map.get` returns `number | undefined`, `document.querySelector` returns `Element | null`, and using the result without a check is an error (TS18048 for \"possibly undefined\", TS18047 for \"possibly null\").",
        "It is part of [`strict`](/config/strict/), arrived with TypeScript 2.0, and catches one of the most common runtime errors in JavaScript: reading a property of `undefined`."
      ],
      "examples": [
        "config/strict-null-checks-on",
        "config/strict-null-checks-off"
      ],
      "sections": [
        {
          "id": "narrowing",
          "heading": "Checking before use",
          "body": [
            "Ordinary JavaScript checks are what the checker understands:"
          ],
          "list": [
            "`if (price !== undefined)` or `if (price)` before the use",
            "optional chaining, `price?.toFixed(2)`, which gives `undefined` instead of throwing",
            "a fallback with `??`: `(prices.get(\"coffee\") ?? 0).toFixed(2)`",
            "`instanceof` for DOM lookups: `if (el instanceof HTMLInputElement)`"
          ]
        },
        {
          "id": "no-bang",
          "heading": "There is no ! in JavaScript",
          "body": [
            "TypeScript files can assert \"not null\" with a postfix `!`. JavaScript cannot; [the alternatives](/types/non-null-assertions/) are a check, a fallback, or a cast in JSDoc."
          ]
        }
      ],
      "gotchas": [
        "A variable that starts as `null` is followed, not left `any`: after `let a = null`, reading `a.length` is TS18047 in TypeScript 5.9. Give it a `@type` when it will hold something else later, so that assignments are checked too.",
        "Turning this on in an existing codebase reports many errors at once; [`noImplicitAny`](/config/no-implicit-any/) first, then this, is the usual order."
      ],
      "related": [
        "config/strict",
        "types/null-and-undefined",
        "types/non-null-assertions",
        "config/no-unchecked-indexed-access",
        "errors/ts18048",
        "errors/ts18047"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: strictNullChecks",
          "url": "https://www.typescriptlang.org/tsconfig/#strictNullChecks",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Type Checking JavaScript Files",
          "url": "https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "strictFunctionTypes",
      "slug": "strict-function-types",
      "title": "strictFunctionTypes",
      "kind": "compilerOption",
      "option": "strictFunctionTypes",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `strict` is on)",
      "ts6Default": "`true`, through `strict` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--strictFunctionTypes",
      "officialDescription": "When assigning functions, check to ensure parameters and the return values are subtype-compatible.",
      "since": "2.6",
      "startWith": "Leave it to [`strict`](/config/strict/); write `\"strictFunctionTypes\": false` only to turn this one check back off",
      "summary": "strictFunctionTypes checks parameter types when one function type is assigned to another. A string-only function cannot stand in for one that gets numbers.",
      "intro": [
        "When you assign a function to a variable or property with a function type, `strictFunctionTypes` checks that the function can handle every argument the type allows. A function that only accepts strings cannot stand in for one that may be called with a number; without the option, TypeScript lets it through.",
        "It is part of [`strict`](/config/strict/) and arrived with TypeScript 2.6."
      ],
      "examples": [
        "config/strict-function-types-on",
        "config/strict-function-types-off"
      ],
      "sections": [
        {
          "id": "methods",
          "heading": "Methods are exempt",
          "body": [
            "TypeScript's 2.6 release notes say the stricter rule applies to function types, not to methods. In JSDoc that is the difference between a property holding a function, `{ log: (value: string) => void }`, which is checked strictly, and the method shorthand, `{ log(value: string): void }`, which is not. Prefer the property form in a `@typedef` when you want the check."
          ]
        }
      ],
      "gotchas": [
        "The example's `log(42)` would call `toUpperCase` on a number at run time; with the option off, nothing reports it."
      ],
      "related": [
        "config/strict",
        "types/function-types",
        "tags/callback",
        "tags/type"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: strictFunctionTypes",
          "url": "https://www.typescriptlang.org/tsconfig/#strictFunctionTypes",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.6 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "strictBindCallApply",
      "slug": "strict-bind-call-apply",
      "title": "strictBindCallApply",
      "kind": "compilerOption",
      "option": "strictBindCallApply",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `strict` is on)",
      "ts6Default": "`true`, through `strict` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--strictBindCallApply",
      "officialDescription": "Check that the arguments for 'bind', 'call', and 'apply' methods match the original function.",
      "since": "3.2",
      "startWith": "Leave it to [`strict`](/config/strict/); write `\"strictBindCallApply\": false` only to turn this one check back off",
      "summary": "strictBindCallApply checks the arguments you pass through bind, call and apply against the function's own parameters, instead of accepting anything.",
      "intro": [
        "`fn.call(thisArg, ...args)`, `fn.apply(thisArg, args)` and `fn.bind(thisArg, ...args)` call a function indirectly. Without `strictBindCallApply`, TypeScript accepts any arguments there; with it, they are checked against the function's parameters, exactly as a direct call would be.",
        "It is part of [`strict`](/config/strict/) and arrived with TypeScript 3.2."
      ],
      "examples": [
        "config/strict-bind-call-apply-on",
        "config/strict-bind-call-apply-off"
      ],
      "sections": [
        {
          "id": "where-it-matters",
          "heading": "Where it shows up in JavaScript",
          "body": [
            "Older JavaScript leans on these methods: borrowing array methods with `Array.prototype.slice.call(arguments)`, binding event handlers with `this.onClick.bind(this)`, and `apply` to spread an array of arguments. With the option on, each of those calls is checked, and `bind` returns a function with the remaining parameters typed."
          ]
        }
      ],
      "gotchas": [
        "The first argument, `thisArg`, is checked against a `@this` type when the function has one; see [`@this`](/tags/this/)."
      ],
      "related": [
        "config/strict",
        "tags/this",
        "config/no-implicit-this"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: strictBindCallApply",
          "url": "https://www.typescriptlang.org/tsconfig/#strictBindCallApply",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 3.2 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "strictPropertyInitialization",
      "slug": "strict-property-initialization",
      "title": "strictPropertyInitialization",
      "kind": "compilerOption",
      "option": "strictPropertyInitialization",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `strict` is on)",
      "ts6Default": "`true`, through `strict` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--strictPropertyInitialization",
      "officialDescription": "Check for class properties that are declared but not set in the constructor.",
      "since": "2.7",
      "startWith": "Leave it to [`strict`](/config/strict/); write `\"strictPropertyInitialization\": false` only to turn this one check back off",
      "summary": "strictPropertyInitialization reports a class field that has a type but is never set, by an initializer or in the constructor (TS2564).",
      "intro": [
        "A class field declared with a type, such as `/** @type {string} */ owner;`, promises that every instance has a string there. `strictPropertyInitialization` checks the promise: the field needs an initializer (`owner = \"\";`) or an assignment in the constructor. If it has neither, it starts out `undefined`, and TypeScript reports TS2564.",
        "It is part of [`strict`](/config/strict/), arrived with TypeScript 2.7, and needs `strictNullChecks`, which `strict` also turns on."
      ],
      "examples": [
        "config/strict-property-initialization-on",
        "config/strict-property-initialization-off"
      ],
      "sections": [
        {
          "id": "fixes",
          "heading": "Three ways to fix it",
          "body": [
            "In a `.js` file:"
          ],
          "list": [
            "give the field a value: `owner = \"\";`",
            "assign it in the constructor, as the example does for `balance`",
            "say it may be missing: `/** @type {string | undefined} */ owner;`"
          ]
        },
        {
          "id": "constructor-only",
          "heading": "Properties set only in the constructor",
          "body": [
            "Many JavaScript classes never declare fields; they assign `this.owner = owner` in the constructor, and TypeScript infers the property from that. Such properties are always set, so this check has nothing to report about them."
          ]
        }
      ],
      "gotchas": [
        "TypeScript files can write `owner!: string` to say \"set elsewhere\". JavaScript has no such syntax; use one of the fixes above.",
        "Without `strictNullChecks` the option is a config error."
      ],
      "related": [
        "config/strict",
        "config/strict-null-checks",
        "tags/type",
        "tags/class",
        "errors/ts2564"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: strictPropertyInitialization",
          "url": "https://www.typescriptlang.org/tsconfig/#strictPropertyInitialization",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.7 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Type Checking JavaScript Files",
          "url": "https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "noImplicitThis",
      "slug": "no-implicit-this",
      "title": "noImplicitThis",
      "kind": "compilerOption",
      "option": "noImplicitThis",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `strict` is on)",
      "ts6Default": "`true`, through `strict` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--noImplicitThis",
      "officialDescription": "Enable error reporting when 'this' is given the type 'any'.",
      "since": "2.0",
      "startWith": "Leave it to [`strict`](/config/strict/); write `\"noImplicitThis\": false` only to turn this one check back off",
      "summary": "noImplicitThis reports this inside a function where TypeScript cannot tell what it is (TS2683). In JavaScript, a @this tag says what it is.",
      "intro": [
        "Inside a plain `function`, `this` depends on how the function is called, so TypeScript often cannot know its type and falls back to `any`. `noImplicitThis` reports those uses (TS2683), so a typo in `this.nmae` cannot slip through.",
        "It is part of [`strict`](/config/strict/) and arrived with TypeScript 2.0. Methods in classes and object literals are not affected: there `this` has a known type."
      ],
      "examples": [
        "config/no-implicit-this-on",
        "config/no-implicit-this-off"
      ],
      "sections": [
        {
          "id": "fix",
          "heading": "Saying what this is",
          "body": [
            "Add a [`@this`](/tags/this/) tag, `/** @this {{ name: string, price: number }} */`, or move the function into the object or class as a method, where `this` is typed for you."
          ]
        }
      ],
      "gotchas": [
        "A function that assigns to `this.something` is treated as a constructor function in a `.js` file, so its `this` is the instance and is never reported.",
        "Arrow functions take `this` from where they are written, so they are never the cause."
      ],
      "related": [
        "tags/this",
        "types/this-parameter",
        "config/strict",
        "config/strict-bind-call-apply",
        "errors/ts2683"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: noImplicitThis",
          "url": "https://www.typescriptlang.org/tsconfig/#noImplicitThis",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "useUnknownInCatchVariables",
      "slug": "use-unknown-in-catch-variables",
      "title": "useUnknownInCatchVariables",
      "kind": "compilerOption",
      "option": "useUnknownInCatchVariables",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `strict` is on)",
      "ts6Default": "`true`, through `strict` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--useUnknownInCatchVariables",
      "officialDescription": "Default catch clause variables as 'unknown' instead of 'any'.",
      "since": "4.4",
      "startWith": "Leave it to [`strict`](/config/strict/); write `\"useUnknownInCatchVariables\": false` only to turn this one check back off",
      "summary": "useUnknownInCatchVariables types the err in catch (err) as unknown instead of any, so you check what was thrown before using err.message (TS18046).",
      "intro": [
        "JavaScript can `throw` any value, not only `Error` objects, so the variable in `catch (err)` can be anything. With `useUnknownInCatchVariables` it is typed `unknown`, and using `err.message` without a check is an error (TS18046). Without it, `err` is `any` and nothing is checked.",
        "It joined [`strict`](/config/strict/) with TypeScript 4.4, so code that passed under `strict` before 4.4 can report errors after an upgrade."
      ],
      "examples": [
        "config/use-unknown-in-catch-variables-on",
        "config/use-unknown-in-catch-variables-off"
      ],
      "sections": [
        {
          "id": "fix",
          "heading": "Checking what was thrown",
          "body": [
            "Narrow before you use it: `err instanceof Error ? err.message : String(err)`. That handles `throw \"oops\"` and other non-errors too, which is the point of the check."
          ]
        }
      ],
      "gotchas": [
        "Promise rejections in `.catch((err) => …)` callbacks are typed `any` regardless of this option; the option covers `catch` clauses only."
      ],
      "related": [
        "config/strict",
        "types/any-and-unknown",
        "types/type-predicates",
        "errors/ts18046"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: useUnknownInCatchVariables",
          "url": "https://www.typescriptlang.org/tsconfig/#useUnknownInCatchVariables",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 4.4 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "alwaysStrict",
      "slug": "always-strict",
      "title": "alwaysStrict",
      "kind": "compilerOption",
      "option": "alwaysStrict",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `strict` is on)",
      "ts6Default": "`true`: setting it to `false` is deprecated ([TypeScript 6.0](/typescript/6-0/#deprecated))",
      "flag": "--alwaysStrict",
      "officialDescription": "Ensure 'use strict' is always emitted.",
      "since": "2.1",
      "startWith": "Leave it to [`strict`](/config/strict/); write `\"alwaysStrict\": false` only to turn this one check back off",
      "summary": "alwaysStrict parses every file in JavaScript strict mode, so reserved words such as package cannot be names. ES modules are strict anyway.",
      "intro": [
        "JavaScript has a strict mode with tighter rules: some words are reserved, `with` is forbidden, deleting a plain variable is an error. ES modules and class bodies are always strict; older scripts are strict only with a `\"use strict\"` line. `alwaysStrict` makes TypeScript parse every file as strict and report what strict mode forbids, such as `package` used as a variable name (TS1212).",
        "It is part of [`strict`](/config/strict/). Its other job, writing `\"use strict\"` into output files, does not apply with `noEmit`. TypeScript 6.0 treats all code as strict and deprecates turning it off."
      ],
      "examples": [
        "config/always-strict-on",
        "config/always-strict-off"
      ],
      "sections": [
        {
          "id": "who-it-affects",
          "heading": "Which files it affects",
          "body": [
            "Only scripts: files that are not modules, such as classic `<script>` files in a browser project. The examples use one (no `import` or `export`, `module: \"esnext\"`, no `\"type\"` in `package.json`). ES modules are strict whether or not the option is on, and in TypeScript 5.9 CommonJS files checked under `module: \"nodenext\"` are treated as strict too."
          ]
        }
      ],
      "gotchas": [
        "Scripts that rely on sloppy-mode behavior (assigning to an undeclared variable to create a global, for example) break when they run as modules; this option shows you those spots before you switch."
      ],
      "related": [
        "config/strict",
        "config/module-detection",
        "config/module",
        "config/check-js"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: alwaysStrict",
          "url": "https://www.typescriptlang.org/tsconfig/#alwaysStrict",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.1 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 6.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "noUncheckedIndexedAccess",
      "slug": "no-unchecked-indexed-access",
      "title": "noUncheckedIndexedAccess",
      "kind": "compilerOption",
      "option": "noUncheckedIndexedAccess",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "flag": "--noUncheckedIndexedAccess",
      "officialDescription": "Add 'undefined' to a type when accessed using an index.",
      "since": "4.1",
      "startWith": "`\"noUncheckedIndexedAccess\": true` once `strict` passes; `tsc --init` in TypeScript 5.9 writes it",
      "summary": "noUncheckedIndexedAccess adds undefined to array elements and index-signature lookups, so names[2] must be checked before use. Not part of strict.",
      "intro": [
        "Under `strict` alone, `names[2]` on a `string[]` is a `string`, even when the array has two elements, and a key looked up in a `Record<string, number>` is a `number` whether or not it exists. `noUncheckedIndexedAccess` adds `undefined` to those lookups, so each one needs a check, like any other value that may be missing.",
        "It arrived with TypeScript 4.1 and is not part of [`strict`](/config/strict/). The strict level of the [jsconfig generator](/tools/jsconfig-generator/) turns it on, and so does the config that `tsc --init` writes in TypeScript 5.9."
      ],
      "examples": [
        "config/no-unchecked-indexed-access-on",
        "config/no-unchecked-indexed-access-off"
      ],
      "sections": [
        {
          "id": "what-changes",
          "heading": "What changes and what does not",
          "body": [
            "Lookups by index or by key gain `undefined`; iteration does not:"
          ],
          "list": [
            "`array[i]`, and destructuring such as `const [first] = array`",
            "`record[key]` and `record.key` for keys that come from an index signature",
            "`for (const item of array)`, `array.forEach` and `array.map` are unchanged, because they only visit elements that exist",
            "tuples keep their exact types: the second element of a `[string, number]` is a `number`"
          ]
        }
      ],
      "gotchas": [
        "Loops written with an index, `for (let i = 0; i < a.length; i++) a[i]…`, report every `a[i]` even though `i` is in range. A `for…of` loop reads better and needs no check."
      ],
      "related": [
        "config/strict-null-checks",
        "config/strict",
        "types/record",
        "types/arrays"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: noUncheckedIndexedAccess",
          "url": "https://www.typescriptlang.org/tsconfig/#noUncheckedIndexedAccess",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 4.1 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.9 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-9.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "exactOptionalPropertyTypes",
      "slug": "exact-optional-property-types",
      "title": "exactOptionalPropertyTypes",
      "kind": "compilerOption",
      "option": "exactOptionalPropertyTypes",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "flag": "--exactOptionalPropertyTypes",
      "officialDescription": "Interpret optional property types as written, rather than adding 'undefined'.",
      "since": "4.4",
      "startWith": "`\"exactOptionalPropertyTypes\": true` if your code tells \"missing\" from \"set to undefined\" (with `in` or `Object.keys`); otherwise leave it out",
      "summary": "exactOptionalPropertyTypes makes an optional property mean \"may be missing\", not \"may be undefined\", so { nickname: undefined } is TS2375.",
      "intro": [
        "An optional property, `@property {string} [nickname]` in JSDoc, normally accepts `undefined` as a value as well as being left out. `exactOptionalPropertyTypes` makes it mean only \"may be left out\": writing `nickname: undefined` becomes an error ([TS2375](/errors/ts2375/)) unless the type says `string | undefined`.",
        "The difference is visible at run time: `\"nickname\" in user` and `Object.keys(user)` see a property set to `undefined` but not a missing one. The option arrived with TypeScript 4.4, is not part of [`strict`](/config/strict/), and needs `strictNullChecks`."
      ],
      "examples": [
        "config/exact-optional-property-types-on",
        "config/exact-optional-property-types-off"
      ],
      "sections": [
        {
          "id": "allowing-undefined",
          "heading": "When undefined is a real value",
          "body": [
            "Say so in the type: `@property {string | undefined} [nickname]` accepts both a missing property and one set to `undefined`. Use it where your code writes `undefined` on purpose, for example to clear a field."
          ]
        }
      ],
      "gotchas": [
        "Spreading options objects often writes `undefined` values (`{ ...defaults, nickname: input.nickname }`), so turning this on in an existing codebase can report many lines that are harmless in practice.",
        "Library types are read with the same rule: passing `undefined` for an optional property of a library's type becomes an error unless that type includes `undefined`."
      ],
      "related": [
        "tags/property",
        "types/optional-parameters",
        "types/object-shapes",
        "config/strict-null-checks"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: exactOptionalPropertyTypes",
          "url": "https://www.typescriptlang.org/tsconfig/#exactOptionalPropertyTypes",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 4.4 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "noImplicitReturns",
      "slug": "no-implicit-returns",
      "title": "noImplicitReturns",
      "kind": "compilerOption",
      "option": "noImplicitReturns",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "flag": "--noImplicitReturns",
      "officialDescription": "Enable error reporting for codepaths that do not explicitly return in a function.",
      "since": "1.8",
      "startWith": "`\"noImplicitReturns\": true`",
      "summary": "noImplicitReturns reports a function where some paths return a value and others fall off the end (TS7030), a common source of a stray undefined.",
      "intro": [
        "A JavaScript function that reaches its closing brace returns `undefined`. When some paths `return` a value and another just ends, that `undefined` is usually a bug: `sign(0)` in the example. `noImplicitReturns` reports the function ([TS7030](/errors/ts7030/), \"Not all code paths return a value\").",
        "It is not part of [`strict`](/config/strict/); the strict level of the [jsconfig generator](/tools/jsconfig-generator/) turns it on."
      ],
      "examples": [
        "config/no-implicit-returns-on",
        "config/no-implicit-returns-off"
      ],
      "sections": [
        {
          "id": "with-returns-tag",
          "heading": "With a @returns tag",
          "body": [
            "When a function has a JSDoc [`@returns`](/tags/returns/) type that does not include `undefined`, `strict` alone already reports a path that falls off the end. This option matters most for functions whose return type is inferred, which in JavaScript is most of them."
          ]
        }
      ],
      "gotchas": [
        "A function that returns nothing on every path is fine; the check is about mixing `return value` with paths that return nothing."
      ],
      "related": [
        "tags/returns",
        "config/no-fallthrough-cases-in-switch",
        "config/strict",
        "errors/ts2366"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: noImplicitReturns",
          "url": "https://www.typescriptlang.org/tsconfig/#noImplicitReturns",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 1.8 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "noFallthroughCasesInSwitch",
      "slug": "no-fallthrough-cases-in-switch",
      "title": "noFallthroughCasesInSwitch",
      "kind": "compilerOption",
      "option": "noFallthroughCasesInSwitch",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "flag": "--noFallthroughCasesInSwitch",
      "officialDescription": "Enable error reporting for fallthrough cases in switch statements.",
      "since": "1.8",
      "startWith": "`\"noFallthroughCasesInSwitch\": true`",
      "summary": "noFallthroughCasesInSwitch reports a switch case that runs on into the next one without break or return (TS7029). Empty cases may still share code.",
      "intro": [
        "In a `switch`, a `case` without `break`, `return` or `throw` runs on into the next case. Sometimes that is intended; more often a `break` is missing. `noFallthroughCasesInSwitch` reports every case that falls through after running code (TS7029).",
        "Empty cases are allowed, so `case \"s\": case \"small\":` can still share one body. The option is not part of [`strict`](/config/strict/); the strict level of the [jsconfig generator](/tools/jsconfig-generator/) turns it on."
      ],
      "examples": [
        "config/no-fallthrough-cases-in-switch-on",
        "config/no-fallthrough-cases-in-switch-off"
      ],
      "sections": [
        {
          "id": "on-purpose",
          "heading": "When you mean to fall through",
          "body": [
            "Rewrite it so the intent is in the code: move the shared part into a function both cases call, or end the first case with an explicit `return`. There is no comment that marks one fall-through as intended."
          ]
        }
      ],
      "gotchas": [
        "A case that ends in `return`, `throw` or `continue` does not fall through, so it is not reported."
      ],
      "related": [
        "config/no-implicit-returns",
        "config/strict",
        "tools/jsconfig-generator",
        "types/discriminated-unions"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: noFallthroughCasesInSwitch",
          "url": "https://www.typescriptlang.org/tsconfig/#noFallthroughCasesInSwitch",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 1.8 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "noImplicitOverride",
      "slug": "no-implicit-override",
      "title": "noImplicitOverride",
      "kind": "compilerOption",
      "option": "noImplicitOverride",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "flag": "--noImplicitOverride",
      "officialDescription": "Ensure overriding members in derived classes are marked with an override modifier.",
      "since": "4.3",
      "startWith": "`\"noImplicitOverride\": true` in code with class hierarchies",
      "summary": "noImplicitOverride requires an @override tag on each method that replaces a base-class method, so renaming the base method cannot silently break it.",
      "intro": [
        "When a subclass method has the same name as a method in its base class, it replaces it. If the base method is later renamed, the subclass method quietly stops overriding anything. `noImplicitOverride` makes every override say so: in a `.js` file, with a JSDoc [`@override`](/tags/override/) tag. A missing tag is TS4119.",
        "Once overrides are marked, a tag on a method that overrides nothing is an error too, so renames in the base class surface right away. The option arrived with TypeScript 4.3, along with the `override` keyword, and is not part of [`strict`](/config/strict/)."
      ],
      "examples": [
        "config/no-implicit-override-on",
        "config/no-implicit-override-off"
      ],
      "sections": [
        {
          "id": "tag-placement",
          "heading": "Where the tag goes",
          "body": [
            "Put `/** @override */` on its own line above the method, as `Circle` does. A JSDoc comment on the same line as the class's opening brace is not attached to the method after it, so the check would still report it."
          ]
        }
      ],
      "gotchas": [
        "An `@override` tag on a method that overrides nothing is reported (TS4122) even without this option."
      ],
      "related": [
        "tags/override",
        "tags/extends",
        "tags/class",
        "errors/ts4119"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: noImplicitOverride",
          "url": "https://www.typescriptlang.org/tsconfig/#noImplicitOverride",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 4.3 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "noUnusedLocals",
      "slug": "no-unused-locals",
      "title": "noUnusedLocals and noUnusedParameters",
      "kind": "compilerOption",
      "option": "noUnusedLocals",
      "alsoCovers": [
        "noUnusedParameters"
      ],
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "flag": "--noUnusedLocals",
      "officialDescription": "Enable error reporting when local variables aren't read.",
      "since": "2.0",
      "startWith": "Optional. Many projects leave both off and let a linter report unused names as warnings",
      "summary": "noUnusedLocals and noUnusedParameters report variables, imports and parameters that are declared and never read (TS6133). A leading _ exempts a parameter.",
      "intro": [
        "`noUnusedLocals` reports local variables, functions and imports that are declared but never read; `noUnusedParameters` does the same for function parameters. Both use TS6133 (\"is declared but its value is never read\"). Exported names are not local, so they are never reported.",
        "Neither is part of [`strict`](/config/strict/). Both arrived with TypeScript 2.0."
      ],
      "examples": [
        "config/no-unused-locals-on",
        "config/no-unused-locals-off"
      ],
      "sections": [
        {
          "id": "underscore",
          "heading": "Keeping a parameter you do not use",
          "body": [
            "A callback often has to accept a parameter it ignores. Start its name with an underscore, as `_context` does in the example, and `noUnusedParameters` leaves it alone."
          ]
        },
        {
          "id": "errors-vs-warnings",
          "heading": "Errors, not warnings",
          "body": [
            "TypeScript reports these as errors, so `npm run lint` fails while you are halfway through a change and a variable is not used yet. That is why many teams leave both off and use a linter rule instead, which can be a warning. Bun's recommended config, for example, sets both to `false`."
          ]
        }
      ],
      "gotchas": [
        "An import used only in a JSDoc type counts as used."
      ],
      "related": [
        "config/strict",
        "tags/import",
        "errors/ts6133"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: noUnusedLocals",
          "url": "https://www.typescriptlang.org/tsconfig/#noUnusedLocals",
          "publisher": "TypeScript"
        },
        {
          "title": "TSConfig Reference: noUnusedParameters",
          "url": "https://www.typescriptlang.org/tsconfig/#noUnusedParameters",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 2.6 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript",
          "url": "https://bun.com/docs/runtime/typescript",
          "publisher": "Bun docs"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "noPropertyAccessFromIndexSignature",
      "slug": "no-property-access-from-index-signature",
      "title": "noPropertyAccessFromIndexSignature",
      "kind": "compilerOption",
      "option": "noPropertyAccessFromIndexSignature",
      "category": "Strictness",
      "tsCategory": "Type Checking",
      "type": "boolean",
      "default": "false",
      "flag": "--noPropertyAccessFromIndexSignature",
      "officialDescription": "Enforces using indexed accessors for keys declared using an indexed type.",
      "since": "4.2",
      "startWith": "Optional: turn it on if you want dot access to mean \"a property the type declares\"",
      "summary": "noPropertyAccessFromIndexSignature makes you write obj[\"key\"] rather than obj.key for keys that come from an index signature, such as process.env.",
      "intro": [
        "An index signature (`Record<string, string>`, or `[key: string]: string` in a type) accepts any key. With this option, dot access is kept for properties the type actually declares, and keys that only the index signature allows must be written with brackets: `settings[\"locale\"]`, not `settings.locale` ([TS4111](/errors/ts4111/)).",
        "The point is that a misspelled declared property looks like a mistake again: `settings.theem` would otherwise be accepted as just another key. The option arrived with TypeScript 4.2 and is not part of [`strict`](/config/strict/)."
      ],
      "examples": [
        "config/no-property-access-from-index-signature-on",
        "config/no-property-access-from-index-signature-off"
      ],
      "sections": [
        {
          "id": "process-env",
          "heading": "process.env",
          "body": [
            "In `@types/node`, `process.env` is an index signature, so with this option on `process.env.PORT` must become `process.env[\"PORT\"]`. That is the most common reason teams leave it off."
          ]
        }
      ],
      "gotchas": [
        "Properties the type declares (`settings.theme`) keep dot access; only keys that come from the index signature need brackets."
      ],
      "related": [
        "types/record",
        "types/indexed-access",
        "config/no-unchecked-indexed-access"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: noPropertyAccessFromIndexSignature",
          "url": "https://www.typescriptlang.org/tsconfig/#noPropertyAccessFromIndexSignature",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 4.2 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "noUncheckedSideEffectImports",
      "slug": "no-unchecked-side-effect-imports",
      "title": "noUncheckedSideEffectImports",
      "kind": "compilerOption",
      "option": "noUncheckedSideEffectImports",
      "category": "Strictness",
      "tsCategory": "Modules",
      "type": "boolean",
      "default": "false",
      "ts6Default": "`true` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--noUncheckedSideEffectImports",
      "officialDescription": "Check side effect imports.",
      "since": "5.6",
      "startWith": "`\"noUncheckedSideEffectImports\": true`; `tsc --init` in TypeScript 5.9 writes it, and 6.0 turns it on by default",
      "summary": "noUncheckedSideEffectImports reports an import that binds nothing, like import \"./polyfills.js\", when its file is missing. On by default from TypeScript 6.0.",
      "intro": [
        "An import with nothing to bind, `import \"./setup.js\"`, runs a file for its side effects. TypeScript used to skip such imports entirely, so a misspelled path passed the check and failed only when the code ran. With `noUncheckedSideEffectImports`, an unresolved side-effect import is reported like any other missing module (TS2307).",
        "It arrived with TypeScript 5.6, is not part of [`strict`](/config/strict/), and is on by default from TypeScript 6.0."
      ],
      "examples": [
        "config/no-unchecked-side-effect-imports-on",
        "config/no-unchecked-side-effect-imports-off"
      ],
      "sections": [
        {
          "id": "css",
          "heading": "Side-effect imports of CSS and other files",
          "body": [
            "Bundler projects often write `import \"./styles.css\"`. With the option on, TypeScript needs to know that such a module exists. TypeScript's 5.6 release notes suggest a declaration file with `declare module \"*.css\" {}`, which covers every CSS import at once."
          ]
        }
      ],
      "gotchas": [
        "TypeScript 6.0 turns it on by default, so after an upgrade a side-effect import that passed before can report TS2307."
      ],
      "related": [
        "config/allow-arbitrary-extensions",
        "config/resolve-json-module",
        "errors/ts2307",
        "typescript/5-6"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: noUncheckedSideEffectImports",
          "url": "https://www.typescriptlang.org/tsconfig/#noUncheckedSideEffectImports",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 5.6 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-6.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 6.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "module",
      "slug": "module",
      "title": "module",
      "kind": "compilerOption",
      "option": "module",
      "category": "Modules and resolution",
      "tsCategory": "Modules",
      "type": "string",
      "default": "commonjs",
      "defaultNote": "(with the 5.9 default target, `es5`; `es2015` for newer targets)",
      "ts6Default": "`esnext` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--module",
      "officialDescription": "Specify what module code is generated.",
      "since": null,
      "startWith": "`\"nodenext\"` for code Node.js runs; `\"preserve\"` with `moduleResolution: \"bundler\"` for code a bundler, Bun or another tool reads first",
      "summary": "module tells the checker which module system your .js files follow: Node's rules with nodenext, a bundler's with preserve. Set it, even with noEmit.",
      "intro": [
        "TypeScript describes `module` in terms of the code it writes, but with `noEmit` nothing is written, and `module` still matters: it tells the checker which module system your files live in. That decides whether each `.js` file is an ES module or CommonJS, which syntax is allowed in it (top-level `await`, `import.meta`), and, unless you set [`moduleResolution`](/config/module-resolution/) yourself, how imports are found.",
        "In a JavaScript project there are two good answers. `\"nodenext\"` follows Node.js: `package.json` `\"type\"`, `.mjs` and `.cjs`, extensions on relative imports, `exports` maps. `\"preserve\"` with `moduleResolution: \"bundler\"` fits code that a bundler or a runtime such as Bun reads first. Leaving `module` out is the one bad answer: in TypeScript 5.9 it then defaults to `commonjs`, as the first example shows."
      ],
      "examples": [
        "config/module-commonjs",
        "config/module-nodenext"
      ],
      "sections": [
        {
          "id": "nodenext",
          "heading": "nodenext: Node's own rules",
          "body": [
            "With `module: \"nodenext\"` (which also sets `moduleResolution` to `nodenext`), the checker reads each file the way Node.js will load it:"
          ],
          "list": [
            "a `.js` file is an ES module when the nearest `package.json` says `\"type\": \"module\"`, and CommonJS otherwise; `.mjs` files are always ES modules and `.cjs` files always CommonJS",
            "relative imports in ES modules need their file extension (TS2835 without it), as Node.js requires",
            "package imports go through the package's `exports` map, with the `import` or `require` condition to match the file",
            "JSON imports in ES modules need `with { type: \"json\" }`",
            "since TypeScript 5.8, a CommonJS file may `require()` an ES module, which Node.js allows without a flag from 20.19 and 22.12"
          ]
        },
        {
          "id": "node-versions",
          "heading": "node16, node18, node20 or nodenext?",
          "body": [
            "`nodenext` moves with Node.js: each TypeScript release can teach it newer behavior. `node16`, `node18` and `node20` are frozen at that Node.js version's rules (`node20` arrived with TypeScript 5.9). Use a frozen value when you need checking to stay put across TypeScript upgrades, or when you support an older Node.js; TypeScript's handbook suggests `node18` for libraries. `nodenext` also implies `target: \"esnext\"` when you leave `target` out, and `node20` implies `es2023`."
          ]
        },
        {
          "id": "bundlers",
          "heading": "preserve and esnext: code a bundler reads",
          "body": [
            "When a bundler, Bun, or a framework tool resolves your imports, Node's rules are too strict (the tool adds extensions for you) or simply not the rules that apply. `module: \"preserve\"` keeps each import as written and implies `moduleResolution: \"bundler\"`; the older pairing is `module: \"esnext\"` with `moduleResolution: \"bundler\"`. Either way the checker allows extensionless relative imports and reads `exports` maps with the `import` condition."
          ]
        },
        {
          "id": "rewrite-extensions",
          "heading": "rewriteRelativeImportExtensions",
          "body": [
            "TypeScript 5.7 added `rewriteRelativeImportExtensions`, which turns `import \"./util.ts\"` into `import \"./util.js\"` in the files `tsc` writes. It does nothing for a `.js` project: there is no output, and imports already end in `.js`. It belongs to TypeScript projects that run `.ts` files directly, for example with Node.js type stripping."
          ]
        }
      ],
      "gotchas": [
        "A config without `module` (and without a recent `target`) is checked as old CommonJS in TypeScript 5.9: top-level `await` and `import.meta` are errors even in a file Node.js runs as an ES module. TypeScript 6.0 changes the default to `esnext`.",
        "`\"type\"` in `package.json` matters only under `node16` to `nodenext`; with `preserve` or `esnext`, TypeScript does not ask whether a file is CommonJS."
      ],
      "faq": [
        {
          "q": "What module setting should a JavaScript project use?",
          "a": "`\"nodenext\"` if Node.js runs the files as they are. `\"preserve\"` (with `\"moduleResolution\": \"bundler\"`) if a bundler or Bun reads them first. The [quick-start setups](/start/) show both."
        }
      ],
      "related": [
        "config/module-resolution",
        "config/module-detection",
        "start/node-esm",
        "start/node-cjs",
        "errors/ts1378",
        "errors/ts2835"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: module",
          "url": "https://www.typescriptlang.org/tsconfig/#module",
          "publisher": "TypeScript"
        },
        {
          "title": "Modules: Reference",
          "url": "https://www.typescriptlang.org/docs/handbook/modules/reference.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Modules: Choosing Compiler Options",
          "url": "https://www.typescriptlang.org/docs/handbook/modules/guides/choosing-compiler-options.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 4.7 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.8 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-8.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.7 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.9 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-9.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 6.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "moduleResolution",
      "slug": "module-resolution",
      "title": "moduleResolution",
      "kind": "compilerOption",
      "option": "moduleResolution",
      "category": "Modules and resolution",
      "tsCategory": "Modules",
      "type": "string",
      "default": "node10",
      "defaultNote": "(with `module: \"commonjs\"`; `module` `nodenext` implies `nodenext`, and `preserve` implies `bundler`)",
      "flag": "--moduleResolution",
      "officialDescription": "Specify how TypeScript looks up a file from a given module specifier.",
      "since": null,
      "startWith": "Usually nothing: let `module` imply it. Write `\"bundler\"` next to `module: \"esnext\"`",
      "summary": "moduleResolution decides how the checker finds the file behind an import: Node's rules with nodenext, a bundler's with bundler. Usually module sets it for you.",
      "intro": [
        "`moduleResolution` is the lookup algorithm: given `\"./format\"` or `\"some-package/sub\"`, which file does the import mean? `nodenext` applies Node's rules (extensions required in ES modules, `exports` maps honored); `bundler` applies the looser rules bundlers share (extensions optional, `exports` read with the `import` condition).",
        "`module: \"nodenext\"` implies `nodenext` and `module: \"preserve\"` implies `bundler`, so most configs never write it. `bundler` arrived with TypeScript 5.0. The old `node10` (also spelled `node`) ignores `exports` maps and is deprecated from TypeScript 6.0; `classic` is removed there."
      ],
      "examples": [
        "config/module-resolution-nodenext",
        "config/module-resolution-bundler"
      ],
      "sections": [
        {
          "id": "which",
          "heading": "Which one matches your project",
          "body": [
            "Choose by who resolves the imports when the code runs. If Node.js loads your files directly, use `nodenext`, so the checker refuses imports that Node.js would refuse. If a bundler, Bun, or a framework's build resolves them, use `bundler`, so the checker accepts what that tool accepts. A browser that loads `<script type=\"module\">` files without a bundler needs exact relative URLs, which `nodenext` with `\"type\": \"module\"` enforces; TypeScript's handbook suggests that pairing for unbundled browser code."
          ]
        }
      ],
      "gotchas": [
        "With `bundler`, the checker accepts `import \"./format\"`, but Node.js would not. Use it only for code that something other than Node.js resolves.",
        "An import the checker cannot resolve is an error only when it binds something; `import \"./polyfill.js\"` with a wrong path passes unless [`noUncheckedSideEffectImports`](/config/no-unchecked-side-effect-imports/) is on."
      ],
      "related": [
        "config/module",
        "config/paths",
        "config/custom-conditions",
        "errors/ts2307",
        "errors/ts2792",
        "errors/ts2835"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: moduleResolution",
          "url": "https://www.typescriptlang.org/tsconfig/#moduleResolution",
          "publisher": "TypeScript"
        },
        {
          "title": "Modules: Reference",
          "url": "https://www.typescriptlang.org/docs/handbook/modules/reference.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Modules: Choosing Compiler Options",
          "url": "https://www.typescriptlang.org/docs/handbook/modules/guides/choosing-compiler-options.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 6.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "moduleDetection",
      "slug": "module-detection",
      "title": "moduleDetection",
      "kind": "compilerOption",
      "option": "moduleDetection",
      "category": "Modules and resolution",
      "tsCategory": "Language and Environment",
      "type": "string",
      "default": "auto",
      "flag": "--moduleDetection",
      "officialDescription": "Control what method is used to detect module-format JS files.",
      "since": "4.7",
      "startWith": "Leave it at `\"auto\"` with `nodenext`. With `bundler` or `preserve`, write `\"force\"`",
      "summary": "moduleDetection decides which files are modules with their own scope. With bundler settings, force stops scripts from sharing one global scope (TS2451).",
      "intro": [
        "A JavaScript file is either a module, with its own top-level scope, or a script, whose top-level names are globals shared with every other script. `moduleDetection` decides which files TypeScript treats as modules. Under `\"auto\"`, the default, a file is a module when it has `import` or `export`, or when its module format says so; `\"force\"` makes every file a module; `\"legacy\"` looks only for `import` and `export`.",
        "It matters when files have no imports or exports. With `module: \"nodenext\"`, Node's rules already make every `.js` file a module, ES or CommonJS. With `bundler` or `preserve`, two such files that each declare `const label` are scripts in one global scope, and TypeScript reports TS2451 in both. The option arrived with TypeScript 4.7."
      ],
      "examples": [
        "config/module-detection-auto",
        "config/module-detection-force"
      ],
      "sections": [
        {
          "id": "when-scripts-are-real",
          "heading": "When files really are scripts",
          "body": [
            "Classic browser `<script>` tags without `type=\"module\"` do share one global scope, so there TS2451 is a real collision and `\"auto\"` is right. Use `\"force\"` when every file is in fact a module: anything a bundler or a modern runtime loads."
          ]
        }
      ],
      "gotchas": [
        "`tsc --init` in TypeScript 5.9 writes `\"moduleDetection\": \"force\"`, and Bun's recommended config sets it too."
      ],
      "related": [
        "config/module",
        "config/module-resolution",
        "config/always-strict",
        "errors/ts2451"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: moduleDetection",
          "url": "https://www.typescriptlang.org/tsconfig/#moduleDetection",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 4.7 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.9 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-9.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "esModuleInterop",
      "slug": "es-module-interop",
      "title": "esModuleInterop and allowSyntheticDefaultImports",
      "kind": "compilerOption",
      "option": "esModuleInterop",
      "alsoCovers": [
        "allowSyntheticDefaultImports"
      ],
      "category": "Modules and resolution",
      "tsCategory": "Interop Constraints",
      "type": "boolean",
      "default": "false",
      "defaultNote": "(on when `module` is `node16` to `nodenext`, or `preserve`)",
      "ts6Default": "`true`, and `false` can no longer be set ([TypeScript 6.0](/typescript/6-0/#deprecated))",
      "flag": "--esModuleInterop",
      "officialDescription": "Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility.",
      "since": "2.7",
      "startWith": "Nothing: a `jsconfig.json` turns on `allowSyntheticDefaultImports`, and `nodenext` and `preserve` imply both",
      "summary": "esModuleInterop and allowSyntheticDefaultImports let you write import express from \"express\" for a CommonJS package. A jsconfig.json already allows it.",
      "intro": [
        "Many npm packages are CommonJS and declare their types with `export =`. Importing one as `import express from \"express\"` needs the checker to accept a default import that the package does not literally have. `allowSyntheticDefaultImports` allows that in the types; `esModuleInterop` also changes the JavaScript `tsc` writes, and turns on `allowSyntheticDefaultImports`.",
        "In a `.js` project you rarely touch either: a file named `jsconfig.json` defaults `allowSyntheticDefaultImports` to `true`, `module: \"nodenext\"` and `\"preserve\"` imply both, and `moduleResolution: \"bundler\"` implies `allowSyntheticDefaultImports`. The failing example has to switch it off on purpose (TS1259)."
      ],
      "examples": [
        "config/es-module-interop-off",
        "config/es-module-interop-default"
      ],
      "sections": [
        {
          "id": "emit",
          "heading": "Why esModuleInterop is mostly about output",
          "body": [
            "The \"additional JavaScript\" in TypeScript's description is the helper code `tsc` adds when it writes CommonJS output. With `noEmit` there is no output, so for a checked JavaScript project only the type side matters, which is `allowSyntheticDefaultImports`."
          ]
        }
      ],
      "gotchas": [
        "Under `nodenext`, what a default import of a CommonJS package gives you follows Node.js: the whole `module.exports` object. A package whose types were written for bundler interop can look different there; trust what Node.js does at run time."
      ],
      "related": [
        "config/module",
        "recipes/type-an-express-handler",
        "config/verbatim-module-syntax",
        "errors/ts1259"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: esModuleInterop",
          "url": "https://www.typescriptlang.org/tsconfig/#esModuleInterop",
          "publisher": "TypeScript"
        },
        {
          "title": "TSConfig Reference: allowSyntheticDefaultImports",
          "url": "https://www.typescriptlang.org/tsconfig/#allowSyntheticDefaultImports",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.7 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 1.8 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-8.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 6.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "paths",
      "slug": "paths",
      "title": "paths and baseUrl",
      "kind": "compilerOption",
      "option": "paths",
      "alsoCovers": [
        "baseUrl"
      ],
      "category": "Modules and resolution",
      "tsCategory": "Modules",
      "type": "object",
      "default": "not set",
      "flag": null,
      "officialDescription": "Specify a set of entries that re-map imports to additional lookup locations.",
      "since": "2.0",
      "startWith": "In a project Node.js runs, prefer a `package.json` `imports` field (`\"#lib/*\"`), which Node.js also understands. Use `paths` for names only a bundler or the checker resolves",
      "summary": "paths maps import names to files for the checker, such as @lib/* to src/lib/*. It does not change how Node.js resolves imports; package.json imports does.",
      "intro": [
        "`paths` maps import specifiers to files: `\"@lib/*\": [\"./src/lib/*\"]` lets `import … from \"@lib/format.js\"` find `src/lib/format.js`. Paths are resolved relative to the config file that sets them. `baseUrl` is an older companion that resolves bare names from one folder; it has not been needed for `paths` since TypeScript 4.1 and is deprecated from 6.0.",
        "The catch for a JavaScript project: `paths` only tells the checker where to look. Nothing rewrites your imports, so Node.js, which reads your files as they are, does not know `@lib` and fails at run time. For code Node.js runs, the `imports` field in `package.json` gives you the same alias in a form both understand, as the third example shows."
      ],
      "examples": [
        "config/paths-off",
        "config/paths-on",
        "config/paths-imports"
      ],
      "sections": [
        {
          "id": "imports-field",
          "heading": "The imports field instead",
          "body": [
            "Node.js supports subpath imports: names starting with `#`, mapped in `package.json` and private to the package. TypeScript reads them under `nodenext` and `bundler` with no config, so the alias works in the checker and in Node.js alike."
          ],
          "snippets": [
            {
              "file": "package.json",
              "from": "config/paths-imports",
              "lang": "json",
              "code": "{\n  \"private\": true,\n  \"type\": \"module\",\n  \"imports\": {\n    \"#lib/*\": \"./src/lib/*\"\n  }\n}"
            }
          ]
        },
        {
          "id": "when-paths",
          "heading": "When paths is the right tool",
          "body": [
            "When something else resolves the alias at run time: a bundler configured with the same alias, a test runner, or a monorepo where workspace links provide the package names and `paths` points the checker at the sources (see [extends](/config/extends/)). Keep the two lists in sync, since nothing checks that they agree."
          ]
        }
      ],
      "gotchas": [
        "`paths` cannot be set on the command line, and `tsc --init` cannot write it; it lives only in a config file.",
        "A `paths` entry in a base config that others `extend` is resolved relative to the base file, not to the config that extends it."
      ],
      "related": [
        "config/module-resolution",
        "config/extends",
        "start/monorepo",
        "config/custom-conditions",
        "errors/ts2307"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: paths",
          "url": "https://www.typescriptlang.org/tsconfig/#paths",
          "publisher": "TypeScript"
        },
        {
          "title": "TSConfig Reference: baseUrl",
          "url": "https://www.typescriptlang.org/tsconfig/#baseUrl",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 4.1 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 6.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Modules: Packages, subpath imports",
          "url": "https://nodejs.org/api/packages.html#subpath-imports",
          "publisher": "Node.js docs"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "customConditions",
      "slug": "custom-conditions",
      "title": "customConditions",
      "kind": "compilerOption",
      "option": "customConditions",
      "category": "Modules and resolution",
      "tsCategory": "Modules",
      "type": "string[]",
      "default": "not set",
      "flag": "--customConditions",
      "officialDescription": "Conditions to set in addition to the resolver-specific defaults when resolving imports.",
      "since": "5.0",
      "startWith": "Only when your runtime or bundler resolves packages with extra conditions: list the same ones, for example `[\"development\"]`",
      "summary": "customConditions adds export conditions, like development, that TypeScript uses when it reads a package's exports map. Match what your runtime or bundler uses.",
      "intro": [
        "A package's `exports` map can point to different files under different conditions: `import`, `require`, `node`, and any names the package invents, such as `development`. Node.js uses the extra ones only when you run it with `--conditions` (`-C`); bundlers have a setting for them. `customConditions` tells the checker to use the same ones, so it reads the files your code will actually load.",
        "It works with `moduleResolution` set to `node16`, `nodenext` or `bundler`, and arrived with TypeScript 5.0."
      ],
      "examples": [
        "config/custom-conditions-off",
        "config/custom-conditions-on"
      ],
      "sections": [
        {
          "id": "keep-in-step",
          "heading": "Keep it in step with the runtime",
          "body": [
            "The examples use a package whose `development` entry exports an extra `trace` function. Checked with the default conditions, `trace` does not exist (TS2305); with `customConditions: [\"development\"]` it does. If you run `node -C development main.js`, the second config describes your program; if you run plain `node main.js`, the first one does, and `trace` really would be missing."
          ]
        }
      ],
      "gotchas": [
        "Conditions are read in the package's order, not yours: the first matching key in the `exports` map wins."
      ],
      "related": [
        "config/module-resolution",
        "config/paths",
        "config/module"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: customConditions",
          "url": "https://www.typescriptlang.org/tsconfig/#customConditions",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 5.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Modules: Packages, conditional exports",
          "url": "https://nodejs.org/api/packages.html#conditional-exports",
          "publisher": "Node.js docs"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "verbatimModuleSyntax",
      "slug": "verbatim-module-syntax",
      "title": "verbatimModuleSyntax",
      "kind": "compilerOption",
      "option": "verbatimModuleSyntax",
      "category": "Modules and resolution",
      "tsCategory": "Interop Constraints",
      "type": "boolean",
      "default": "false",
      "flag": "--verbatimModuleSyntax",
      "officialDescription": "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.",
      "since": "5.0",
      "startWith": "Optional in a `.js` project. Turn it on if some files are CommonJS: it reports `export` syntax in files TypeScript treats as CommonJS",
      "summary": "verbatimModuleSyntax keeps imports exactly as written in tsc's output. In a .js project its one effect is to report ESM exports in a CommonJS file.",
      "intro": [
        "In a TypeScript project, `verbatimModuleSyntax` makes `tsc` write every import and export as written, dropping only those marked `type`. That is about output, and a JavaScript project with `noEmit` has none. It also cannot change how you import types: JavaScript has no `import type` syntax, and type imports in JSDoc (`@import`, `import(\"./x.js\").T`) never reach the output anyway.",
        "What it does do in a `.js` file: under `module: \"nodenext\"`, it reports ESM `export` syntax in a file TypeScript treats as CommonJS (TS1287): a `.cjs` file, or a `.js` file whose `package.json` says `\"type\": \"commonjs\"` or has no `type` field. Without the option, TypeScript checks such a file quietly. Node.js refuses `export` in a file it loads as CommonJS; recent Node.js versions run a `.js` file without a `type` field as an ES module when it uses ES module syntax, so the error matters most where `\"type\": \"commonjs\"` is set. It arrived with TypeScript 5.0, and `tsc --init` writes it in 5.9."
      ],
      "examples": [
        "config/verbatim-module-syntax-on",
        "config/verbatim-module-syntax-off"
      ],
      "sections": [
        {
          "id": "types-in-js",
          "heading": "Importing a type in JavaScript",
          "body": [
            "With or without this option, `import { Config } from \"./types.js\"` for a name that is only a `@typedef` is an error in a `.js` file ([TS18042](/errors/ts18042/)): JavaScript imports are values. Use [`@import`](/tags/import/) (TypeScript 5.5 and later) or an [`import()` type](/types/import-types/) in JSDoc."
          ]
        }
      ],
      "gotchas": [
        "In TypeScript 5.9 an `import` statement in a CommonJS `.js` file is not reported under this option, only `export`; Node.js rejects both."
      ],
      "related": [
        "config/module",
        "tags/import",
        "types/import-types",
        "config/es-module-interop"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: verbatimModuleSyntax",
          "url": "https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 5.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.9 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-9.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "target",
      "slug": "target",
      "title": "target",
      "kind": "compilerOption",
      "option": "target",
      "category": "Environment",
      "tsCategory": "Language and Environment",
      "type": "string",
      "default": "es5",
      "defaultNote": "(`module` `nodenext` implies `esnext`, and `node20` implies `es2023`)",
      "ts6Default": "the newest ECMAScript year (`es2025` in 6.0); `es5` is deprecated ([TypeScript 6.0](/typescript/6-0/#deprecated))",
      "flag": "--target",
      "officialDescription": "Set the JavaScript language version for emitted JavaScript and include compatible library declarations.",
      "since": null,
      "startWith": "The ECMAScript year your oldest supported runtime fully implements, for example `\"es2022\"` or `\"es2024\"`",
      "summary": "target names the JavaScript version your runtime has. With noEmit it picks which built-in APIs exist: Promise.withResolvers needs es2024.",
      "intro": [
        "`target` names an ECMAScript version. When `tsc` writes output, it rewrites newer syntax down to that version. With `noEmit` nothing is rewritten, so in a JavaScript project `target` does one job: unless you set [`lib`](/config/lib/), it picks the built-in declarations, and so decides which methods exist. `Promise.withResolvers` and `Object.groupBy` are ES2024; with `target: \"es2022\"` they are TS2550.",
        "Pick the newest year that every runtime you support implements in full. In TypeScript 5.9 a config without `target` gets `es5`, unless `module` is `nodenext` (which implies `esnext`) or `node20` (`es2023`). TypeScript 6.0 changes the default to the newest year and deprecates `es5`."
      ],
      "examples": [
        "config/target-es2022",
        "config/target-es2024"
      ],
      "sections": [
        {
          "id": "syntax",
          "heading": "What target does not do with noEmit",
          "body": [
            "It does not make old runtimes understand new syntax: your files run exactly as written. If you write `??=` or a class field and set `target: \"es2017\"`, nothing reports that an ES2017 engine cannot parse them, because `tsc` would rewrite them if it wrote output. A few features it cannot rewrite are errors, such as BigInt literals below `es2020` (TS2737). Treat `target` as a statement about your runtime that picks the library, not as a syntax compatibility check."
          ]
        },
        {
          "id": "with-lib",
          "heading": "target and lib together",
          "body": [
            "Without `lib`, `target` also brings the browser (DOM) declarations. Setting `lib` replaces that whole default, so with `lib` set, `target` no longer chooses any declarations. A Node.js project that wants ES2024 methods and no DOM can write `\"lib\": [\"es2024\"]` and leave `target` to `module: \"nodenext\"`."
          ]
        }
      ],
      "gotchas": [
        "`target: \"esnext\"` follows whatever TypeScript considers the newest year, so it can let through a method your runtime does not have yet. A fixed year is more honest about your runtime."
      ],
      "related": [
        "config/lib",
        "config/module",
        "config/types",
        "errors/ts2583",
        "errors/ts2550",
        "errors/ts1378"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: target",
          "url": "https://www.typescriptlang.org/tsconfig/#target",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 5.7 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.9 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-9.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 6.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "lib",
      "slug": "lib",
      "title": "lib",
      "kind": "compilerOption",
      "option": "lib",
      "category": "Environment",
      "tsCategory": "Language and Environment",
      "type": "string[]",
      "default": "the target's libraries, plus dom",
      "flag": "--lib",
      "officialDescription": "Specify a set of bundled library declaration files that describe the target runtime environment.",
      "since": "2.0",
      "startWith": "Leave it out for browser code. For code with no DOM (Node.js, Bun, Cloudflare), list the ES year alone: `[\"es2024\"]`",
      "summary": "lib picks the built-in declarations the checker knows: an ECMAScript year, and dom for browsers. Without dom there is no document, and no console either.",
      "intro": [
        "`lib` lists TypeScript's own declaration files for built-in APIs: the ECMAScript standard library by year (`es2022`, `es2024`, `esnext`), the browser DOM (`dom`, `dom.iterable`), and a few more such as `webworker`. Without `lib`, TypeScript picks the files for your [`target`](/config/target/) and adds `dom`. With `lib` set, you get exactly the list.",
        "The list is a statement about where your code runs. A browser project wants `dom`; a server or edge project wants it gone, so `document` is an error instead of a crash. One surprise: `console` is declared by the DOM library (and by `@types/node`), not by ECMAScript, so `lib: [\"es2022\"]` with no other types makes `console.log` an error too (TS2584)."
      ],
      "examples": [
        "config/lib-no-dom",
        "config/lib-dom"
      ],
      "sections": [
        {
          "id": "common-lists",
          "heading": "Lists that fit the usual projects",
          "body": [
            "Starting points that match the checked setups in the [quick start](/start/):"
          ],
          "list": [
            "browser, no bundler: `[\"es2022\", \"dom\", \"dom.iterable\"]` (`dom.iterable` lets you loop over a `NodeList` with `for…of`)",
            "Node.js: `[\"es2024\"]`, with `\"types\": [\"node\"]` for `process`, `console` and the built-in modules",
            "Cloudflare: `[\"es2024\"]` with the platform types in `types` (see the [quick start](/start/))",
            "Bun: `[\"esnext\"]` with `\"types\": [\"bun\"]`, which is what Bun's documentation recommends"
          ]
        }
      ],
      "gotchas": [
        "Setting `lib` replaces the default list; it does not add to it. `\"lib\": [\"dom\"]` alone loses the ECMAScript library.",
        "A type package can bring globals of its own regardless of `lib`: `@types/node` declares `console`, `setTimeout` and more."
      ],
      "related": [
        "config/target",
        "config/types",
        "start/browser",
        "errors/ts2583",
        "errors/ts2584",
        "errors/ts2550"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: lib",
          "url": "https://www.typescriptlang.org/tsconfig/#lib",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript",
          "url": "https://bun.com/docs/runtime/typescript",
          "publisher": "Bun docs"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "types",
      "slug": "types",
      "title": "types and typeRoots",
      "kind": "compilerOption",
      "option": "types",
      "alsoCovers": [
        "typeRoots"
      ],
      "category": "Environment",
      "tsCategory": "Modules",
      "type": "string[]",
      "default": "every package in node_modules/@types",
      "ts6Default": "`[]` ([TypeScript 6.0](/typescript/6-0/#defaults))",
      "flag": "--types",
      "officialDescription": "Specify type package names to be included without being referenced in a source file.",
      "since": null,
      "startWith": "List the global types you use: `[\"node\"]` for Node.js, `[\"bun\"]` for Bun, `[]` for a browser project",
      "summary": "types lists the @types packages whose globals the checker loads, like node for process. Without it, TypeScript 5.9 loads every @types package; 6.0 loads none.",
      "intro": [
        "Some type packages describe globals rather than modules: `@types/node` declares `process`, `Buffer` and the `node:` modules; `@types/bun` declares `Bun`. Nothing in your code imports them, so TypeScript needs to be told to load them. `types` is that list: `\"types\": [\"node\"]` loads `@types/node`, and `process` exists (without it, TS2591).",
        "Leave `types` out and TypeScript 5.9 loads every package in `node_modules/@types`, including ones a dependency pulled in that have nothing to do with your code. TypeScript 6.0 changes the default to `[]`. Writing the list keeps a config meaning the same thing in both, and keeps stray globals out."
      ],
      "examples": [
        "config/types-empty",
        "config/types-node"
      ],
      "sections": [
        {
          "id": "imports-unaffected",
          "heading": "Imported packages are not affected",
          "body": [
            "`types` controls only packages loaded for their globals. `import express from \"express\"` still finds `@types/express` with `\"types\": []`. And a package you import can bring globals of its own: `@types/express` loads `@types/node`, so in a project that imports Express, `process` exists even with an empty `types` list."
          ]
        },
        {
          "id": "type-roots",
          "heading": "typeRoots",
          "body": [
            "`typeRoots` changes where TypeScript looks for those packages, replacing the default of every `node_modules/@types` folder from the config file upward. JavaScript projects almost never need it; a folder of your own `.d.ts` files is simpler to add through `include`."
          ]
        }
      ],
      "gotchas": [
        "`\"types\": [\"node\"]` without `@types/node` installed is an error (TS2688). Install the version that matches the Node.js you run."
      ],
      "related": [
        "config/lib",
        "config/target",
        "start/node-esm",
        "errors/ts2584",
        "errors/ts2580",
        "errors/ts2591"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: types",
          "url": "https://www.typescriptlang.org/tsconfig/#types",
          "publisher": "TypeScript"
        },
        {
          "title": "TSConfig Reference: typeRoots",
          "url": "https://www.typescriptlang.org/tsconfig/#typeRoots",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 6.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "@types/node",
          "url": "https://www.npmjs.com/package/@types/node",
          "publisher": "npm"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "jsx",
      "slug": "jsx",
      "title": "jsx",
      "kind": "compilerOption",
      "option": "jsx",
      "category": "Environment",
      "tsCategory": "Language and Environment",
      "type": "string",
      "default": "not set",
      "flag": "--jsx",
      "officialDescription": "Specify what JSX code is generated.",
      "since": null,
      "startWith": "`\"preserve\"` when a bundler or framework compiles your JSX; `\"react-jsx\"` (with `jsxImportSource` for other libraries) to match a React-style runtime",
      "summary": "jsx lets the checker read JSX in .jsx files. Without it, any JSX is TS17004; with it, elements and props are checked against your framework's JSX types.",
      "intro": [
        "JSX is not JavaScript, so the checker reads it only when `jsx` is set; until then every element is TS17004. In a checked JavaScript project, the value mostly says who compiles the JSX: `\"preserve\"` leaves it to your bundler or framework, `\"react-jsx\"` describes React's automatic runtime (and other libraries through `jsxImportSource`).",
        "Once it is set, JSX in `.jsx` files is checked like everything else: expressions inside braces, component props from JSDoc, element names against the `JSX` namespace your framework's types provide."
      ],
      "examples": [
        "config/jsx-off",
        "config/jsx-preserve"
      ],
      "sections": [
        {
          "id": "include-jsx",
          "heading": "Including .jsx files",
          "body": [
            "An `include` pattern that names `*.js` does not match `.jsx`. Write `\"src/**/*.jsx\"` too, or a folder name such as `\"src\"`, which picks up both. The examples include their `.jsx` file by pattern and declare a tiny `JSX` namespace in a `.d.ts`; a real project gets that namespace from its framework's types package."
          ]
        }
      ],
      "gotchas": [
        "`tsc --init` in TypeScript 5.9 writes `\"jsx\": \"react-jsx\"`. In a project without JSX it does nothing; in a project whose JSX is not React, change it."
      ],
      "related": [
        "config/include",
        "tags/param",
        "config/types",
        "errors/ts17004",
        "errors/ts7026"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: jsx",
          "url": "https://www.typescriptlang.org/tsconfig/#jsx",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 4.1 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.9 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-9.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "forceConsistentCasingInFileNames",
      "slug": "force-consistent-casing-in-file-names",
      "title": "forceConsistentCasingInFileNames",
      "kind": "compilerOption",
      "option": "forceConsistentCasingInFileNames",
      "category": "Environment",
      "tsCategory": "Interop Constraints",
      "type": "boolean",
      "default": "true",
      "flag": "--forceConsistentCasingInFileNames",
      "officialDescription": "Ensure that casing is correct in imports.",
      "since": null,
      "startWith": "Leave it at the default, `true`",
      "summary": "forceConsistentCasingInFileNames reports an import whose letter case differs from the file name, which works on macOS and Windows and fails on Linux.",
      "intro": [
        "macOS and Windows usually ignore letter case in file names, so `import { formatPrice } from \"./Format.js\"` finds `format.js` there. Linux does not, so the same code fails on a Linux server or CI machine. `forceConsistentCasingInFileNames` makes the checker report the mismatch on case-insensitive systems too (TS1149), so it shows up before the code reaches a Linux machine.",
        "It is on by default in TypeScript 5.9. There is nothing to set; just do not turn it off."
      ],
      "examples": [],
      "sections": [
        {
          "id": "no-example",
          "heading": "Why this page has no checked example",
          "body": [
            "The result depends on the machine. On a case-insensitive file system, the wrong-case import resolves and the option reports TS1149; on a case-sensitive one, such as most Linux machines, the file is not found at all and the import is a missing-module error, with or without the option. An example checked on one kind of machine would show a different error on the other, so this page describes it instead."
          ]
        }
      ],
      "gotchas": [
        "The option covers imports and the files the config lists. A path your code builds as a string at run time, such as `new URL(\"./Data.json\", import.meta.url)`, is not checked."
      ],
      "related": [
        "config/module-resolution",
        "config/check-js",
        "errors/ts2307",
        "config/include"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: forceConsistentCasingInFileNames",
          "url": "https://www.typescriptlang.org/tsconfig/#forceConsistentCasingInFileNames",
          "publisher": "TypeScript"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "include",
      "slug": "include",
      "title": "include",
      "kind": "topLevel",
      "option": "include",
      "category": "Files",
      "type": "string[]",
      "default": "[\"**/*\"]",
      "defaultNote": "(when `files` is not set)",
      "flag": null,
      "officialDescription": "Specifies a list of glob patterns that match files to be included in compilation.",
      "descriptionSource": "schemastore",
      "since": "2.0",
      "startWith": "`[\"src/**/*.js\"]` or `[\"src\"]`: the folders with your code, so build output and scripts stay out",
      "summary": "include lists the files and folders the checker starts from, as globs relative to jsconfig.json. A folder name picks up every .js file under it.",
      "intro": [
        "`include` is the starting list of files to check: glob patterns resolved relative to the folder that holds the config file. Without `include` (and without `files`), TypeScript starts from every supported file under that folder, minus the [`exclude`](/config/exclude/) list.",
        "In a JavaScript project the supported files include `.js`, `.jsx`, `.mjs` and `.cjs`, because a `jsconfig.json` allows JavaScript. A pattern that ends in a folder name, such as `\"src\"`, takes every supported file under it, `.ts` and `.jsx` too; a pattern like `\"src/**/*.js\"` takes exactly what it says."
      ],
      "examples": [
        "config/include-folder"
      ],
      "sections": [
        {
          "id": "patterns",
          "heading": "The patterns",
          "body": [
            "Three wildcards, as in most glob tools:"
          ],
          "list": [
            "`*` matches any characters within one folder name, `?` matches one character",
            "`**/` matches any number of folders, including none",
            "a pattern without an extension or a wildcard in its last part is a folder: every supported file under it"
          ]
        },
        {
          "id": "imports-pull-files-in",
          "heading": "Imports pull files in",
          "body": [
            "`include` is where the checker starts, not a fence. A file outside it that an included file imports joins the program and is checked too (with `checkJs` on), as [`exclude`](/config/exclude/) shows."
          ]
        }
      ],
      "gotchas": [
        "Test files often live outside `src`; add `\"test/**/*.js\"` to check them too, as the [jsconfig generator](/tools/jsconfig-generator/) does by default."
      ],
      "related": [
        "config/exclude",
        "config/files",
        "config/extends",
        "config/jsx"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: include",
          "url": "https://www.typescriptlang.org/tsconfig/#include",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "tsconfig.json schema",
          "url": "https://json.schemastore.org/tsconfig.json",
          "publisher": "SchemaStore"
        },
        {
          "title": "jsconfig.json",
          "url": "https://code.visualstudio.com/docs/languages/jsconfig",
          "publisher": "Visual Studio Code docs"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "exclude",
      "slug": "exclude",
      "title": "exclude",
      "kind": "topLevel",
      "option": "exclude",
      "category": "Files",
      "type": "string[]",
      "default": "[\"node_modules\", \"bower_components\", \"jspm_packages\"]",
      "defaultNote": "(plus `outDir` when one is set)",
      "flag": null,
      "officialDescription": "Specifies a list of files to be excluded from compilation.",
      "descriptionSource": "schemastore",
      "since": null,
      "startWith": "Folders inside an `include` pattern that the checker should not start from, such as `[\"src/vendor\"]`. It does not stop imports",
      "summary": "exclude removes files from what include matched. It does not keep a file out of the program: an imported file is still read, and with checkJs, still checked.",
      "intro": [
        "`exclude` filters the files that [`include`](/config/include/) matched. Its patterns work the same way, relative to the config file, and by default it leaves out `node_modules` and two older package folders.",
        "What it does not do surprises most people: it does not keep a file out of the program. If an included file imports an excluded one, the excluded file is read, and with `checkJs` on, checked and reported, as the example shows. To stop checking a file that is still imported, put [`// @ts-nocheck`](/config/ts-nocheck/) at its top."
      ],
      "examples": [
        "config/exclude-imported"
      ],
      "sections": [
        {
          "id": "when-useful",
          "heading": "When exclude helps",
          "body": [
            "For files nothing imports: build output, vendored copies of libraries, fixtures, a `scratch` folder. Those are the files that only reach the program through `include`, so `exclude` really keeps them out."
          ]
        }
      ],
      "gotchas": [
        "Setting `exclude` replaces the default list, but there is no need to add `node_modules` back: in TypeScript 5.9 a `**` pattern in `include` never walks into `node_modules` anyway."
      ],
      "related": [
        "config/include",
        "config/files",
        "config/check-js"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: exclude",
          "url": "https://www.typescriptlang.org/tsconfig/#exclude",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "tsconfig.json schema",
          "url": "https://json.schemastore.org/tsconfig.json",
          "publisher": "SchemaStore"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "files",
      "slug": "files",
      "title": "files",
      "kind": "topLevel",
      "option": "files",
      "category": "Files",
      "type": "string[]",
      "default": "not set",
      "flag": null,
      "officialDescription": "Specifies an allowlist of files to include in the program.",
      "descriptionSource": "schemastore",
      "since": null,
      "startWith": "Rarely needed: `include` with a folder or pattern is easier to keep up to date",
      "summary": "files names the exact files the checker starts from, with no globs. Files they import are checked too, and a missing file is a config error.",
      "intro": [
        "`files` is the exact-list version of [`include`](/config/include/): file paths, no patterns, relative to the config file. A path that does not exist is an error. When both are set, the program starts from both lists.",
        "As with `include`, imports pull more files in: start from `src/main.js` alone and every file it imports is read and checked, as the example shows. That makes `files` handy for an entry-point-only config, such as one that checks a script and nothing else."
      ],
      "examples": [
        "config/files-list"
      ],
      "sections": [
        {
          "id": "entry-point",
          "heading": "A config for one entry point",
          "body": [
            "A small repository can keep a second config, say `jsconfig.scripts.json`, with `\"files\": [\"scripts/release.js\"]`, and check it with `tsc -p jsconfig.scripts.json`. Everything that script imports is checked with it, and nothing else is."
          ]
        }
      ],
      "gotchas": [
        "With `files` set and no `include`, the default `include` of everything no longer applies."
      ],
      "related": [
        "config/include",
        "config/exclude",
        "config/extends"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: files",
          "url": "https://www.typescriptlang.org/tsconfig/#files",
          "publisher": "TypeScript"
        },
        {
          "title": "tsconfig.json schema",
          "url": "https://json.schemastore.org/tsconfig.json",
          "publisher": "SchemaStore"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "extends",
      "slug": "extends",
      "title": "extends",
      "kind": "topLevel",
      "option": "extends",
      "category": "Files",
      "type": "string or string[]",
      "default": "not set",
      "flag": null,
      "officialDescription": "Path to base configuration file to inherit from.",
      "descriptionSource": "schemastore",
      "since": "2.1",
      "startWith": "`\"./jsconfig.base.json\"` when several configs share options: one per package in a monorepo, or one for publishing types",
      "summary": "extends makes a config inherit another config file's options, so several jsconfig.json files can share one base. Files lists are replaced, not merged.",
      "intro": [
        "`extends` names a config file to start from. Its `compilerOptions` come first and yours override them one option at a time; `files`, `include` and `exclude` are replaced as a whole when you set them. Relative paths in each file, such as `paths` entries, are resolved relative to the file they are written in.",
        "It arrived with TypeScript 2.1. Since 3.2 the name can be a package in `node_modules`, and since 5.0 it can be a list, where later files win."
      ],
      "examples": [
        "config/extends-base"
      ],
      "sections": [
        {
          "id": "jsconfig-defaults",
          "heading": "Extending a jsconfig.json brings its defaults",
          "body": [
            "A file named `jsconfig.json` has defaults of its own (`allowJs`, `noEmit`, `skipLibCheck` and more). A config that extends one inherits them, written or not. That matters for a second config that should write files: it inherits `noEmit: true` and writes nothing until it sets `\"noEmit\": false`, as on the [declaration page](/config/declaration/)."
          ]
        },
        {
          "id": "monorepo",
          "heading": "One base for many packages",
          "body": [
            "In a repository with several packages, give each package a small `jsconfig.json` that extends a shared one and sets its own `include`. Editors then check each file with the config of its package, and one place holds the strictness level for all of them. The [monorepo setup](/start/monorepo/) is a complete example."
          ],
          "snippets": [
            {
              "file": "packages/app/jsconfig.json",
              "from": "start/monorepo",
              "lang": "json",
              "code": "{\n  \"extends\": \"../../jsconfig.json\",\n  \"include\": [\"src/**/*.js\"]\n}"
            }
          ]
        }
      ],
      "gotchas": [
        "`references` is the one top-level key that is never inherited."
      ],
      "related": [
        "start/monorepo",
        "config/include",
        "config/declaration",
        "config/paths"
      ],
      "sources": [
        {
          "title": "TSConfig Reference: extends",
          "url": "https://www.typescriptlang.org/tsconfig/#extends",
          "publisher": "TypeScript"
        },
        {
          "title": "TypeScript 2.1 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 3.2 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-2.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 5.0 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "tsconfig.json schema",
          "url": "https://json.schemastore.org/tsconfig.json",
          "publisher": "SchemaStore"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "ts-check",
      "slug": "ts-check",
      "title": "// @ts-check",
      "kind": "directive",
      "option": "// @ts-check",
      "category": "Comment directives",
      "since": "2.3",
      "appliesTo": "file",
      "withCheckJs": "Nothing more: every `.js` file is checked already",
      "withoutCheckJs": "Checks this one file, with the options in your config",
      "summary": "// @ts-check at the top of a .js file turns on type checking for that one file, even with checkJs off. Where to put it, and when to use it instead of checkJs.",
      "intro": [
        "`// @ts-check` is a comment that opts one JavaScript file into checking. Put it before the first line of code and the file is checked as if [`checkJs`](/config/check-js/) were on, using the rest of your config (`strict`, `lib`, `types` and so on). It arrived together with `checkJs`, with TypeScript 2.3.",
        "It is the gentle way to start: no config change, one file at a time, and editors such as VS Code honor it with no `jsconfig.json` at all. Once most files have it, switch to `checkJs` and mark the exceptions with [`// @ts-nocheck`](/config/ts-nocheck/) instead."
      ],
      "examples": [
        "config/check-js-pragma"
      ],
      "sections": [
        {
          "id": "placement",
          "heading": "Where it has to go",
          "body": [
            "Anywhere before the first line of code: after a license header or other comments is fine, after an `import` or any statement is too late, and the comment is then ignored without a warning. If a file has both `// @ts-check` and `// @ts-nocheck`, the later of the two wins."
          ]
        },
        {
          "id": "without-config",
          "heading": "Without a jsconfig.json",
          "body": [
            "When no config file applies, an editor checks a file with `// @ts-check` using its own default options, which need not match what `tsc` would use. A project that cares about the result should still have a `jsconfig.json`, so the editor and `tsc -p jsconfig.json` in CI agree."
          ]
        }
      ],
      "gotchas": [
        "`.ts` files are always checked; the comment does nothing there.",
        "A comment after the first statement is ignored without a warning, so a misplaced `// @ts-check` looks like a file with no errors."
      ],
      "faq": [
        {
          "q": "Should I use // @ts-check or checkJs?",
          "a": "`checkJs` for a project you control: every file is checked and new files cannot slip through. `// @ts-check` while migrating an existing codebase file by file, or for a single script that lives outside any project."
        }
      ],
      "related": [
        "config/check-js",
        "config/ts-nocheck",
        "config/ts-expect-error",
        "start/deno",
        "editors/vs-code"
      ],
      "sources": [
        {
          "title": "JS Projects Utilizing TypeScript",
          "url": "https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 2.3 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "Type Checking JavaScript Files",
          "url": "https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "JavaScript in Visual Studio Code: type checking",
          "url": "https://code.visualstudio.com/docs/nodejs/working-with-javascript#_type-checking-javascript",
          "publisher": "Visual Studio Code docs"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "ts-nocheck",
      "slug": "ts-nocheck",
      "title": "// @ts-nocheck",
      "kind": "directive",
      "option": "// @ts-nocheck",
      "category": "Comment directives",
      "since": "2.3",
      "appliesTo": "file",
      "withCheckJs": "Skips this file: no errors are reported in it, but its types still reach the files that import it",
      "withoutCheckJs": "Nothing: the file is not checked anyway",
      "summary": "// @ts-nocheck at the top of a file turns checking off for that file while checkJs stays on for the rest. The file's types still reach its importers.",
      "intro": [
        "`// @ts-nocheck` is the opposite of [`// @ts-check`](/config/ts-check/): written before the first line of code, it stops error reporting for that one file while [`checkJs`](/config/check-js/) keeps checking every other file. It arrived for JavaScript files with TypeScript 2.3, and `.ts` files have honored it since 3.7.",
        "The file is still part of the program. Its JSDoc still types what it exports, so a file that imports `total` from it is checked against those types; only the mistakes inside the skipped file go unreported, as the two examples show."
      ],
      "examples": [
        "config/ts-nocheck-on",
        "config/ts-nocheck-off"
      ],
      "sections": [
        {
          "id": "migration",
          "heading": "Using it during a migration",
          "body": [
            "Turn on `checkJs` for the whole project, add `// @ts-nocheck` to the files that report too much, and remove the comments one file at a time. New files are checked from the start, and `grep -l \"@ts-nocheck\"` lists what is left."
          ]
        }
      ],
      "gotchas": [
        "If a file has both `// @ts-check` and `// @ts-nocheck`, the later of the two wins.",
        "Like `// @ts-check`, it counts only before the first line of code."
      ],
      "related": [
        "config/ts-check",
        "config/check-js",
        "config/allow-js"
      ],
      "sources": [
        {
          "title": "JS Projects Utilizing TypeScript",
          "url": "https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 2.3 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 3.7 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "ts-ignore",
      "slug": "ts-ignore",
      "title": "// @ts-ignore",
      "kind": "directive",
      "option": "// @ts-ignore",
      "category": "Comment directives",
      "since": "2.3",
      "appliesTo": "next line",
      "withCheckJs": "Silences every error on the next line",
      "withoutCheckJs": "Nothing, unless the file starts with `// @ts-check`",
      "summary": "// @ts-ignore silences every error on the next line, now and later. Prefer // @ts-expect-error, which tells you when there is nothing left to silence.",
      "intro": [
        "`// @ts-ignore` on its own line silences every error on the line after it. It came with `checkJs` for JavaScript files, with TypeScript 2.3 (TypeScript's release notes date `.ts` support to 2.6).",
        "The trouble is \"every error, now and later\": once the original problem is fixed, the comment stays and silently swallows the next mistake on that line, as the example shows. [`// @ts-expect-error`](/config/ts-expect-error/) does the same job and is reported once it has nothing to silence, so it is almost always the better choice."
      ],
      "examples": [
        "config/ts-ignore-hides"
      ],
      "sections": [
        {
          "id": "when",
          "heading": "When @ts-ignore is still the right comment",
          "body": [
            "When the same line errors under one setup and not another, for example code checked by two TypeScript versions or two configs. `// @ts-expect-error` would be reported as unused in the setup without the error; `// @ts-ignore` is quiet in both."
          ]
        }
      ],
      "gotchas": [
        "It covers one line only: the line right after the comment. An error that TypeScript reports on a later line of a multi-line statement is not silenced.",
        "Anything after `@ts-ignore` on the same comment line is free text, so `// @ts-ignore: legacy API` documents why."
      ],
      "related": [
        "config/ts-expect-error",
        "config/ts-check",
        "config/ts-nocheck"
      ],
      "sources": [
        {
          "title": "JS Projects Utilizing TypeScript",
          "url": "https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 2.3 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-3.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 2.6 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    },
    {
      "id": "ts-expect-error",
      "slug": "ts-expect-error",
      "title": "// @ts-expect-error",
      "kind": "directive",
      "option": "// @ts-expect-error",
      "category": "Comment directives",
      "since": "3.9",
      "appliesTo": "next line",
      "withCheckJs": "Silences the errors on the next line, and is itself an error (TS2578) when that line has none",
      "withoutCheckJs": "Nothing, unless the file starts with `// @ts-check`",
      "summary": "// @ts-expect-error silences the errors on the next line, and reports TS2578 once that line has none, so a fixed problem cannot leave a stale comment.",
      "intro": [
        "`// @ts-expect-error` on its own line says \"the next line has an error, on purpose\". TypeScript silences the errors on that line, and if the line has none, it reports the comment itself: TS2578, \"Unused '@ts-expect-error' directive\". It arrived with TypeScript 3.9.",
        "That makes it the safe way to keep a known error for now: when someone fixes the line, the comment fails `npm run lint` and gets removed, instead of lingering to hide the next mistake the way [`// @ts-ignore`](/config/ts-ignore/) can."
      ],
      "examples": [
        "config/ts-expect-error"
      ],
      "sections": [
        {
          "id": "reasons",
          "heading": "Say why",
          "body": [
            "Text after the directive on the same line is ignored by the checker, so write the reason there: `// @ts-expect-error: the old API passed strings`. The first call in the example does exactly that."
          ]
        },
        {
          "id": "same-line",
          "heading": "It has to be on the line above",
          "body": [
            "The directive applies to the line that follows it. A block comment at the start of the same line, `/* @ts-expect-error */ formatPrice(\"1\")`, does not count: in TypeScript 5.9 the error on that line is still reported, and so is the directive, as unused."
          ]
        }
      ],
      "gotchas": [
        "Tests that check a function rejects bad input are the classic use: `// @ts-expect-error` above `formatPrice(\"1999\")` in a test file documents the type and proves it still holds.",
        "In a file that is not checked (no `checkJs`, no `// @ts-check`) the comment does nothing and is never reported."
      ],
      "related": [
        "config/ts-ignore",
        "config/ts-check",
        "config/check-js",
        "errors/ts2578"
      ],
      "sources": [
        {
          "title": "JS Projects Utilizing TypeScript",
          "url": "https://www.typescriptlang.org/docs/handbook/intro-to-js-ts.html",
          "publisher": "TypeScript handbook"
        },
        {
          "title": "TypeScript 3.9 release notes",
          "url": "https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html",
          "publisher": "TypeScript handbook"
        }
      ],
      "updated": "2026-10-20"
    }
  ]
}
