DevAcademy
LearnTypeScripttsconfig Deep Dive
AdvancedTypeScript

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

OptionPurpose
targetWhich JavaScript version the output is compiled to
moduleWhich module system the output uses (ESNext, CommonJS, etc.)
libWhich built-in type definitions are available (DOM, ES2020, etc.)
strictEnables all strict type-checking flags at once
esModuleInteropImproves interop between CommonJS and ES module imports
skipLibCheckSkips type-checking of .d.ts files, speeding up compilation
outDirWhere compiled JavaScript is written
include / excludeWhich 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

FlagWhat It Catches
noImplicitAnyValues that would silently fall back to the any type
strictNullChecksUsing a possibly null/undefined value without checking it first
strictFunctionTypesUnsound function parameter type checking
strictPropertyInitializationClass 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.

Interview Questions

Quick Quiz

1. What does the target option control?

2. Is noUncheckedIndexedAccess included in strict mode by default?

3. What does skipLibCheck do?