100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
TypeScript

Configuring tsconfig.json in TypeScript

How tsconfig.json controls TypeScript compiler behavior, including strictness, target/module output, file inclusion, and output directories.

Modules & ToolingIntermediate13 min readJul 8, 2026
Analogies

1. Introduction

tsconfig.json is the configuration file that tells the TypeScript compiler (tsc) how to compile a project: which files to include, what JavaScript version and module format to output, how strict type checking should be, and where to place compiled files. Placing a tsconfig.json at the root of a directory also marks that directory as the root of a TypeScript project, which editors like VS Code use to provide accurate IntelliSense and error checking.

🏏

Cricket analogy: A ground's pitch report tells the groundskeeper how to prepare the surface, which format to support, and where results get recorded, just as tsconfig.json tells tsc which files to compile, what JS version and module format to output, and where to place results.

A well-tuned tsconfig.json is one of the biggest levers for both type safety and build performance in a real project. Running tsc --init scaffolds a starter file with common options commented out, and most production projects then adjust strictness, target/module settings, and file inclusion rules to match their runtime environment (browser, Node.js, bundler).

🏏

Cricket analogy: Just as tuning net-practice intensity based on whether the next match is T20 or a Test is one of the biggest levers for a team's performance, tuning tsconfig.json's strictness, target, and module settings to match the runtime (browser, Node.js, bundler) is one of the biggest levers for a project's safety and build performance.

2. Syntax

json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "declaration": true,
    "sourceMap": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

3. Explanation

tsconfig.json controls compiler behavior through the top-level compilerOptions object plus include/exclude (and optionally files), which control which files are compiled. Among compilerOptions, key options like strict, target, module, outDir, noImplicitAny, and strictNullChecks significantly affect type safety: target sets the ECMAScript version of emitted JavaScript (affecting which syntax/APIs are downleveled), module sets the emitted module system (CommonJS, ESNext, etc.), and outDir/rootDir control where compiled output goes and how the source tree maps to it.

🏏

Cricket analogy: The compilerOptions object is like a coach's master playbook, while include/exclude are like the squad selection list; within it, target decides which era's rules apply (helmet regulations, DRS availability), and outDir decides which stadium the final match gets played in.

strict (bundles multiple strict checks) is a single flag that enables a whole family of stricter type-checking flags at once — including noImplicitAny (disallows variables/parameters implicitly typed as any), strictNullChecks (treats null/undefined as distinct types that must be explicitly handled), strictFunctionTypes, strictBindCallApply, and several others. Turning on strict: true is the single most impactful setting for catching real bugs, and it is the recommended default for all new TypeScript projects. include/exclude control which files are compiled: include lists glob patterns of files to bring into the program, while exclude removes matching files (commonly node_modules, build output, and test files) even if they'd otherwise match include.

🏏

Cricket analogy: Turning on strict: true is like a captain enforcing full fielding-drill discipline at once, no dropped catches (noImplicitAny), no ignoring a batter's null run-out call (strictNullChecks), while include/exclude are the squad list that keeps injured or reserve players (node_modules, test files) out of the matchday XI.

extends lets one tsconfig.json inherit settings from another (e.g., a shared tsconfig.base.json across a monorepo's packages), and references combined with "composite": true enables TypeScript's project references feature for incrementally building multi-package repositories faster.

Gotcha: exclude only affects which files TypeScript directly compiles as part of the program — it does NOT stop a file from being type-checked if it's still reachable via an import from an included file. Excluding node_modules doesn't prevent type errors from a broken @types package if something in src imports it; and forgetting to enable strict (or individually enabling noImplicitAny/strictNullChecks) silently allows any-typed values and unchecked null/undefined access to slip through, which is one of the most common causes of runtime TypeErrors in supposedly type-safe code.

4. Example

typescript
// tsconfig.json for a Node.js CLI tool
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "CommonJS",
    "moduleResolution": "node",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "esModuleInterop": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "dist"]
}

// src/greet.ts
export function greet(name: string | null): string {
  if (name === null) {
    return "Hello, stranger!";
  }
  return `Hello, ${name}!`;
}

5. Output

text
Running `tsc` with the config above compiles src/greet.ts to dist/greet.js targeting ES2022 syntax with CommonJS module.exports.

With "strictNullChecks": true, calling greet(undefined) is a COMPILE-TIME ERROR:
  Argument of type 'undefined' is not assignable to parameter of type 'string | null'.

Without strictNullChecks (strict: false), the same call would compile without error and risk a runtime issue if `name` were used unsafely elsewhere without a null check.

Removing `src/greet.ts` from the include pattern (or adding it to exclude) would make `tsc` skip it, and any file importing it would then fail to resolve the module during compilation.

6. Key Takeaways

  • tsconfig.json controls compiler behavior via compilerOptions plus include/exclude to determine which files are compiled.
  • strict: true bundles multiple checks (noImplicitAny, strictNullChecks, and more) and is the recommended default for new projects.
  • target sets the emitted ECMAScript version; module sets the emitted module system (CommonJS, ESNext, etc.).
  • outDir/rootDir control where compiled output goes and how the source tree structure is mirrored there.
  • exclude prevents direct compilation of matching files but does not block type-checking of files still reachable via imports.
  • extends and project references (composite/references) support sharing config and speeding up builds across monorepo packages.

Practice what you learned

Was this page helpful?

Topics covered

#TypeScript#TypeScriptProgrammingStudyNotes#Programming#ConfiguringTsconfigJsonInTypeScript#Configuring#Tsconfig#Json#Syntax#StudyNotes#SkillVeris