The compiler configuration file that controls how TypeScript transforms your code. Understanding it unlocks full control of your project.
When you run tsc, TypeScript looks for a tsconfig.json file to understand how to compile your project. It controls which files to include, which JavaScript version to target, and how strict the type checking should be.
Generate one automatically:
tsc --init
{
// Compiler options
"compilerOptions": {
// --- Target & Module ---
"target": "ES2021", // output JS version
"module": "commonjs", // module system
"lib": ["ES2021", "DOM"], // type definitions to include
// --- Strictness ---
"strict": true, // enables ALL strict checks
"noImplicitAny": true, // error on implicit 'any'
"strictNullChecks": true, // null/undefined are separate types
// --- Output ---
"outDir": "./dist", // where compiled JS goes
"rootDir": "./src", // where your TS source lives
"sourceMap": true, // generate .map files for debugging
"declaration": true, // generate .d.ts files
// --- Paths ---
"baseUrl": ".",
"paths": {
"@utils/*": ["src/utils/*"],
"@types/*": ["src/types/*"]
},
// --- Extras ---
"esModuleInterop": true, // better CommonJS/ESM interop
"resolveJsonModule": true, // import .json files
"skipLibCheck": true // skip type checking of .d.ts files
},
// Which files to include/exclude
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}
Controls what version of JavaScript TypeScript compiles your code into. Older targets support more browsers but produce more verbose code.
Setting "strict": true is the single most important thing you can do for your project. It enables a collection of strict checks all at once:
💡 Always start new projects with "strict": true. It's much harder to enable later on an existing codebase.
Paths let you replace ugly relative imports like ../../utils/helpers with clean aliases like @utils/helpers.
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@utils/*": ["src/utils/*"],
"@components/*": ["src/components/*"],
"@types/*": ["src/types/*"]
}
}
}
// ❌ Before — fragile relative paths import { formatDate } from '../../../utils/date'; import { Button } from '../../components/Button'; // ✅ After — clean aliases import { formatDate } from '@utils/date'; import { Button } from '@components/Button';
⚠️ Path aliases in tsconfig only work for TypeScript type checking. For runtime bundling you also need to configure your bundler (webpack, vite, etc.) with the same aliases.
Node.js API:
{ "compilerOptions": { "target": "ES2021", "module": "commonjs",
"strict": true, "outDir": "dist", "rootDir": "src" } }
React (with Vite):
{ "compilerOptions": { "target": "ES2020", "module": "ESNext",
"lib": ["ES2020", "DOM"], "jsx": "react-jsx",
"strict": true, "moduleResolution": "bundler" } }