Chapter 21: TypeScript Configuration
TypeScript Configuration (mainly the famous tsconfig.json file) exactly like we’re sitting together in Hyderabad, laptop open, chai on the table, and we’re setting up a real project step by step.
I’m going to explain it very slowly, very practically, and with realistic 2025–2026 examples that people actually use in production (React/Next.js, Node/NestJS, libraries, monorepos, etc.).
1. What is tsconfig.json really? (the honest explanation)
The tsconfig.json file is the brain of your TypeScript project.
- It tells the TypeScript compiler (tsc) →
- Which files to compile
- How strict to be
- What JavaScript version to output
- Where to put the compiled .js files
- How to resolve imports
- Whether to check types in .d.ts files or skip them for speed
- … and hundreds of other tiny (but sometimes critical) decisions
Important facts in 2026:
- If there is no tsconfig.json → TypeScript uses very loose defaults (almost like plain JS with types added on top — dangerous!)
- Almost every serious TS project has one (or many in monorepos)
- Modern tools (Vite, Next.js, esbuild, swc, tsup, vite-node, etc.) read tsconfig.json even when they don’t use tsc for transpilation (they use it for type-checking + path aliases + module resolution)
2. How to create your first tsconfig.json
Simplest way:
|
0 1 2 3 4 5 6 7 |
# Inside your project folder npx tsc --init |
→ This creates a very commented tsconfig.json with almost every possible option (great for learning, but too noisy).
Many people delete 80% of the comments and start from a minimal version.
3. Real-world minimal tsconfig.json in 2026 (good starting point)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
{ "compilerOptions": { // Modern JavaScript output (most projects in 2026) "target": "ES2022", "module": "ESNext", "moduleResolution": "bundler", // Vite, Next.js, Parcel, esbuild, rollup, etc. // Strictness — catch bugs early (highly recommended!) "strict": true, // Very useful speed & safety options "skipLibCheck": true, // Skip type checking of .d.ts files → much faster "esModuleInterop": true, // Better import interop with CommonJS "allowSyntheticDefaultImports": true,// Allow default import from non-ES modules "forceConsistentCasingInFileNames": true, // Where files are & where output goes "rootDir": "./src", "outDir": "./dist", // For JSX / React (if you use React) "jsx": "react-jsx", // Better incremental builds & editor experience "incremental": true, "isolatedModules": true, // Required by many bundlers (Vite, esbuild, swc) "noUncheckedIndexedAccess": true }, // Which files/folders to include "include": ["src/**/*"], // Usually exclude these "exclude": ["node_modules", "dist", "**/*.spec.ts", "**/*.test.ts"] } |
This is already very good for most frontend (React/Vite/Next.js) or modern Node projects in 2026.
4. The most important compilerOptions groups (explained like a teacher)
| Group | Most important flags (2026) | Why people care / what it does | Recommendation level |
|---|---|---|---|
| Output / Compatibility | target, module, moduleResolution, lib | Controls emitted JS version & how imports are resolved | ★★★★★ |
| Strictness / Safety | strict, noImplicitAny, strictNullChecks, exactOptionalPropertyTypes | Catch 70–90% more bugs at compile time | ★★★★★ |
| Speed | skipLibCheck, incremental, isolatedModules, noCheck | Make tsc –noEmit or tsc -b 2–10× faster in large projects | ★★★★★ |
| Paths & Aliases | baseUrl, paths | Import aliases like @components/Button instead of ../../../components/Button | ★★★★ |
| JSX / React | jsx, jsxImportSource | Modern React 18+ → “react-jsx” | ★★★★ (if React) |
| Declarations | declaration, declarationMap, emitDeclarationOnly | Generate .d.ts files (needed when publishing npm packages) | ★★★★ (libraries) |
| Node.js specific | moduleResolution: “nodenext”, module: “nodenext” | For pure ESM Node.js projects (very strict & modern) | ★★★ (Node ESM) |
| Bundler friendly | verbatimModuleSyntax, moduleResolution: “bundler” | Required by Vite / Rolldown / Turbopack / esbuild in many cases | ★★★★ |
5. Realistic examples for different project types (2026 style)
A. Modern React + Vite / Next.js App
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
{ "compilerOptions": { "target": "ES2022", "lib": ["ES2022", "DOM", "DOM.Iterable"], "module": "ESNext", "moduleResolution": "bundler", "jsx": "react-jsx", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "isolatedModules": true, "noUncheckedIndexedAccess": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] } }, "include": ["src"], "exclude": ["node_modules", "dist"] } |
B. Library / NPM package (needs .d.ts files)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "declaration": true, "declarationMap": true, "outDir": "./dist", "rootDir": "./src", "strict": true, "skipLibCheck": true, "verbatimModuleSyntax": true, "noEmit": false }, "include": ["src"], "exclude": ["**/*.test.ts", "**/*.spec.ts"] } |
C. Very strict monorepo / enterprise style (maximum safety)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
{ "compilerOptions": { "strict": true, "noImplicitAny": true, "strictNullChecks": true, "noImplicitThis": true, "useUnknownInCatchVariables": true, "noUnusedLocals": true, "noUnusedParameters": true, "exactOptionalPropertyTypes": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noFallthroughCasesInSwitch": true, "skipLibCheck": true, "incremental": true } } |
6. Quick cheat-sheet — flags most people enable in 2026
| Flag | Typical value | Why almost everyone uses it now |
|---|---|---|
| strict | true | Baseline for serious TS code |
| skipLibCheck | true | 2–5× faster tsc, especially with many @types/* |
| isolatedModules | true | Required by Vite/esbuild/swc |
| moduleResolution | “bundler” or “nodenext” | Modern bundlers or strict Node ESM |
| verbatimModuleSyntax | true | Cleaner imports, catches mistakes early |
| incremental | true | Much faster repeated builds |
| jsx | “react-jsx” | React 17+ / 18+ default |
7. Common advanced patterns
-
Multiple tsconfigs (very common in monorepos / libraries)
- tsconfig.json (base strict settings)
- tsconfig.build.json → extends base, adds outDir, noEmit: false
- tsconfig.test.json → adds “types”: [“vitest/globals”], includes test files
-
extends for shared config
|
0 1 2 3 4 5 6 7 8 9 10 |
// tsconfig.base.json { "compilerOptions": { "strict": true, "skipLibCheck": true } } // tsconfig.json { "extends": "./tsconfig.base.json", ... } |
Your mini homework (do this today!)
- Run npx tsc –init in a new folder
- Replace everything with the React+Vite example above
- Add “baseUrl”: “.”, “paths”: { “@/*”: [“src/*”] }
- Create src/index.ts → import something from ‘@/utils’
- See if VS Code autocompletes the alias
Any confusion? Want me to explain one group deeper?
- Strict mode flags in detail
- Paths & aliases with real monorepo example
- Node.js ESM vs bundler differences
- How to debug tsconfig problems
Just tell me — we’ll zoom right in! 😄
