tsconfig Deep Dive
Understand the most important tsconfig.json compiler options and what each one actually controls.
Reading Time
18 min
Lesson
Lesson 29 of 30
Revisiting tsconfig.json
tsconfig.json configures how the TypeScript compiler behaves. This lesson goes deeper into the options that matter most for real projects.
A More Complete tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "Bundler",
"lib": ["ES2020", "DOM"],
"strict": true,
"noUncheckedIndexedAccess": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "dist",
"declaration": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}Key Options Explained
| Option | Purpose |
|---|---|
| target | Which JavaScript version the output is compiled to |
| module | Which module system the output uses (ESNext, CommonJS, etc.) |
| lib | Which built-in type definitions are available (DOM, ES2020, etc.) |
| strict | Enables all strict type-checking flags at once |
| esModuleInterop | Improves interop between CommonJS and ES module imports |
| skipLibCheck | Skips type-checking of .d.ts files, speeding up compilation |
| outDir | Where compiled JavaScript is written |
| include / exclude | Which files the compiler processes |
What strict Actually Enables
strict is itself a shorthand that turns on several individual flags together, including strictNullChecks, noImplicitAny, and strictFunctionTypes — each catching a different category of mistake.
Flags Included in strict
| Flag | What It Catches |
|---|---|
| noImplicitAny | Values that would silently fall back to the any type |
| strictNullChecks | Using a possibly null/undefined value without checking it first |
| strictFunctionTypes | Unsound function parameter type checking |
| strictPropertyInitialization | Class properties that are never initialized |
noUncheckedIndexedAccess
This extra safety flag (not included in strict) makes indexing into an object or array with an index signature return T | undefined instead of just T, correctly reflecting that the key might not actually exist.
noUncheckedIndexedAccess in Action
const scores: Record<string, number> = { alice: 90 };
const bobScore = scores["bob"];
// Without the flag: typed as 'number' (misleading — it's actually undefined)
// With the flag: typed as 'number | undefined' (accurate)target vs lib
target controls what JavaScript syntax the output uses (and is down-leveled for older environments). lib controls which type definitions are available for you to use in your code — they’re independent settings that often get confused.
Best Practice
Start new projects with strict: true and skipLibCheck: true, and add noUncheckedIndexedAccess once your team is comfortable — it catches a very real class of bugs that plain strict mode misses.