TypeScript course menu
tsconfig.json Explained: strict Mode and the Compiler Options That Matter
A practical guide to tsconfig.json: what strict mode enables, target and lib, module and moduleResolution, outDir and rootDir, noEmit, extra safety options like noUncheckedIndexedAccess, extends, include and exclude, and recommended configurations for Node.js and front-end projects.
On this page
tsconfig.json tells the TypeScript compiler which files belong to the project and how to check and compile them. There are over a hundred options, but a handful matter for almost every project.
A modern starting point#
{
"compilerOptions": {
"target": "es2022",
"lib": ["es2023"],
"module": "nodenext",
"moduleResolution": "nodenext",
"strict": true,
"noUncheckedIndexedAccess": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true,
"outDir": "dist",
"rootDir": "src",
"sourceMap": true
},
"include": ["src"]
}For a front-end project built with a bundler (Vite, Next.js), typical differences are "lib": ["es2023", "dom", "dom.iterable"], "moduleResolution": "bundler", "jsx": "react-jsx" for React, and "noEmit": true (the bundler produces the JavaScript; tsc only type-checks).
strict#
"strict": true switches on a family of checks. It should be on in every new project:
Without strict mode, this compiles; with it, TypeScript catches the bug:
function greet(name) {
return "Hello, " + name.toUpperCase();
}error TS7006: Parameter 'name' implicitly has an 'any' type.Migrating an old JavaScript project? Turn options on one at a time, but aim for full strict mode.
Extra safety options#
These are not part of strict but are worth considering:
noUncheckedIndexedAccess in action:
// with "noUncheckedIndexedAccess": true
const scores: number[] = [72, 95];
const first: number = scores[0];error TS2322: Type 'number | undefined' is not assignable to type 'number'.(The examples on this site are checked with strict; this block also enables noUncheckedIndexedAccess to show its effect.)
target and lib#
targetsets which JavaScript version is output. Syntax newer than the target is converted (for example, optional chaining to older checks). For modern browsers and Node.js,es2022or later is typical.libsets which built-in APIs TypeScript knows about.es2023adds types for features liketoSorted;domaddsdocument,windowandHTMLElement. If TypeScript says a built-in method "does not exist", yourlibmay be too old.
Note that lib only provides types; it does not add the feature to old browsers.
module and moduleResolution#
See Modules and Imports.
Output options#
include, exclude and extends#
includelists the files or folders to compile (["src"]);excluderemoves some (such as test fixtures).node_modulesis excluded by default.extendsreuses another configuration. Shared base configs are published on npm, for example in the@tsconfig/scope:
{
"extends": "@tsconfig/node22/tsconfig.json",
"compilerOptions": { "outDir": "dist" }
}How the examples in this course are checked#
The code in this course is checked with --strict, target ES2022, the es2023 and dom libraries, nodenext modules and skipLibCheck, and @types/node for examples that use Node.js modules.
Practice#
Practice exercise
A React front end is built with Vite. Write a tsconfig.json with strict checking, safe indexed access, DOM types, bundler module resolution, the React JSX transform, and no JavaScript output from tsc, including only the src folder.
Show solution
{
"compilerOptions": {
"target": "es2022",
"lib": ["es2023", "dom", "dom.iterable"],
"module": "esnext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"noUncheckedIndexedAccess": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true,
"noEmit": true
},
"include": ["src"]
}Vite compiles the TypeScript for the browser; npx tsc (or a typecheck script) only checks types.
Key takeaway#
Finished this lesson?