Lesson
You know how to write TypeScript. Now let's learn how to configure the compilerWhat is compiler?A program that translates code you write into a language your computer can execute. It also catches errors before your code runs.. The tsconfig.json file is the control center for TypeScript projects, it tells the compiler what to check, what to output, and how strict to be.
Creating your tsconfig.jsonWhat is json?A text format for exchanging data between systems. It uses key-value pairs and arrays, and every programming language can read and write it.
# Generate a default config with helpful comments
npx tsc --initA solid starting configuration for most projects:
json
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}02
Understanding the target option
The target option tells TypeScript which version of JavaScript to compile to.
| Target | JavaScript Version | When to Use |
|---|---|---|
ES5 | 2009 | Legacy browsers, IE11 support |
ES2015 / ES6 | 2015 | Modern browser support |
ES2020 | 2020 | Most Node.js and modern browsers |
ESNext | Latest | Bleeding edge, may need polyfills |
The same TypeScript code compiles differently depending on your target:
// TypeScript input
const greet = (name: string) => `Hello, ${name}`;
const user = { name: 'John' }?.name ?? 'Anonymous';// Compiled to ES5 (extensive transformation)
var greet = function (name) { return "Hello, " + name; };
var _a;
var user = ((_a = { name: 'John' }) === null || _a === void 0 ? void 0 : _a.name) || 'Anonymous';// Compiled to ES2020 (keeps modern syntax)
const greet = (name) => `Hello, ${name}`;
const user = { name: 'John' }?.name ?? 'Anonymous';03
The strict flag: Your safety net
If you only remember one setting, make it "strict": true. This single flag enables a suite of strict type-checking options that catch the most bugs.
Option enabled by strict | What it enforces |
|---|---|
noImplicitAny | Variables must have known types |
strictNullChecks | null and undefined are separate types |
strictFunctionTypes | Function parameters are checked strictly |
strictPropertyInitialization | Class properties must be initialized |
noImplicitThis | this must have a known type |
alwaysStrict | Enforces strict mode in output |
Why strictNullChecks matters most
// Without strictNullChecks - compiles, crashes at runtime
function greet(name: string) {
console.log(name.toUpperCase());
}
greet(null); // Runtime error!
// With strictNullChecks - TypeScript forces you to handle null
function greetSafe(name: string | null) {
if (name !== null) {
console.log(name.toUpperCase()); // OK - TypeScript knows it's string
}
}04
Organizing your project
json
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}rootDir: Where your.tsfiles liveoutDir: Where compiled.jsfiles gosourceMap: Enables debugging TypeScript in the browserinclude: Which files to compile (glob patterns)exclude: Which files to skip
05
Path mappingWhat is path mapping?A tsconfig.json feature that lets you define aliases for import paths (e.g., @/ → src/) to avoid long relative imports. for clean imports
json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"]
}
}
}// Instead of messy relative paths:
import { Button } from '../../../components/Button';
// Use clean absolute paths:
import { Button } from '@components/Button';06
Configuration presets
| Project type | Key settings |
|---|---|
| Node.js backend | target: ES2020, module: commonjs, strict: true |
| React frontend | target: ES2020, module: ES2020, jsx: react-jsx, noEmit: true |
| Library package | target: ES2015, declaration: true, declarationMap: true |
07
Quick reference
| Option | What it does | Recommended value |
|---|---|---|
target | JavaScript version to compile to | ES2020 |
module | Module system for imports/exports | commonjs (Node) or ES2020 (bundler) |
strict | Enables all strict type checks | true, always |
outDir | Where compiled files go | ./dist |
rootDir | Where source files live | ./src |
sourceMap | Debug TypeScript in the browser | true in dev |
declaration | Generate .d.ts type files | true for libraries |
skipLibCheck | Skip type checking of .d.ts files | true for faster builds |
AI pitfall, weakening your config. When AI tools generate a
tsconfig.json or troubleshoot type errors, they often suggest "strict": false or adding "skipLibCheck": true as a fix. Turning off strict mode is like removing your seatbelt because it's uncomfortable, it doesn't fix anything, it just hides the problems. If strict mode produces errors, fix the code, not the config. The errors are telling you about real bugs.