TLDR
tsconfig.json is the config file for every TypeScript project. It tells the TypeScript compiler what to check and how to build your code. Run tsc --init to create one. The key options you need to know are target, module, strict, outDir, and rootDir. Always turn on strict mode. It saves you from many bugs.
What is tsconfig.json?
tsconfig.json is a file that lives at the root of your TypeScript project. It controls how TypeScript compiles your code.
When you run tsc in your terminal, TypeScript looks for this file first. It reads your settings and uses them to type-check and compile your .ts files.
Without this file, the TypeScript compiler uses its default settings. Those defaults are not always the best for your project. That is why you should always create and customize your own tsconfig.json.
How to Create tsconfig.json
You do not have to write this file by hand. TypeScript gives you a command to create one.
Step 1: Make sure TypeScript is installed.
npm install -g typescript
Step 2: Run the init command in your project folder.
tsc --init
This creates a tsconfig.json file with many options inside it. Most of them are commented out.
Your project folder should look like this:
my-project/
├── src/
│ └── index.ts
├── tsconfig.json
└── package.json
The Structure of tsconfig.json
A tsconfig.json file has a few top-level keys. Here is what each one does:
| Key | What It Does |
|---|---|
compilerOptions |
Controls how TypeScript compiles your code |
include |
Tells TypeScript which folders or files to compile |
exclude |
Tells TypeScript which folders or files to skip |
files |
Lists specific files to include (rarely used) |
extends |
Lets you inherit settings from another config file |
The most important key is compilerOptions. This is where all the action happens.
Here is a basic example of the full structure:
{
"compilerOptions": {
"target": "ES2020",
"module": "CommonJS",
"strict": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src"],
"exclude": ["node_modules"]
}
Core Compiler Options Explained
There are hundreds of compiler options. You do not need to know all of them. Here are the ones you will use in almost every project.
| Option | Type | Default | What It Does |
|---|---|---|---|
target |
string | ES3 |
Sets the JavaScript version for output |
module |
string | depends | Sets how modules are handled |
strict |
boolean | false |
Turns on all strict type checks |
outDir |
string | none | Folder where compiled JS files go |
rootDir |
string | none | Root folder of your TypeScript source files |
lib |
array | depends | Built-in type definitions to include |
sourceMap |
boolean | false |
Creates .map files for debugging |
declaration |
boolean | false |
Creates .d.ts type files |
skipLibCheck |
boolean | false |
Skips type checking of .d.ts files |
esModuleInterop |
boolean | false |
Allows default imports from CommonJS modules |
resolveJsonModule |
boolean | false |
Lets you import .json files |
How to Set the target Option
The target option tells TypeScript which version of JavaScript to compile your code to.
For example, if you set target to ES5, TypeScript turns your modern arrow functions into old function expressions. If you set it to ES2020, it keeps modern syntax as-is.
Which target should you pick?
| Target | Use It When |
|---|---|
ES5 |
You need to support very old browsers |
ES6 / ES2015
|
Older Node.js projects |
ES2017 |
You want async/await in the output |
ES2020 |
Good default for most modern projects |
ES2022 |
Best for modern Node.js (v16+) |
ESNext |
Always use the latest JS features |
{
"compilerOptions": {
"target": "ES2022"
}
}
Tip:
ES2022is a safe and modern choice for most new projects in 2025. It is stable and supported by all modern browsers and Node.js versions.
How to Set the module Option
The module option controls how TypeScript handles import and export statements in the compiled output.
This option depends on where your code will run.
module Value |
Use It When |
|---|---|
CommonJS |
Building for Node.js |
ESNext |
Building for modern browsers or bundlers like Vite |
NodeNext |
Building for Node.js with native ES modules support |
AMD |
Old browser projects (rarely used now) |
{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS"
}
}
For most Node.js projects, use CommonJS. For browser projects with a bundler like Vite or Webpack, use ESNext.
How to Enable Strict Mode
strict is the most important option in tsconfig.json. It turns on a group of type-checking rules all at once.
When strict is true, TypeScript becomes much better at catching bugs before your code runs.
Here is what strict: true turns on for you:
| Option Enabled | What It Prevents |
|---|---|
strictNullChecks |
Using null or undefined where a value is expected |
noImplicitAny |
Using variables without a type |
strictFunctionTypes |
Wrong function parameter types |
strictPropertyInitialization |
Class properties that are never set |
useUnknownInCatchVariables |
Unsafe use of catch error variables |
{
"compilerOptions": {
"strict": true
}
}
Always set strict: true. Starting without it and adding it later is painful. You will have a lot of errors to fix. Start strict from day one.
How to Set outDir and rootDir
These two options work together. They control where TypeScript reads your source files from and where it puts the compiled JavaScript files.
-
rootDirpoints to your TypeScript source folder (usually./src) -
outDirpoints to the folder where compiled files should go (usually./dist)
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist"
}
}
After running tsc, your project will look like this:
my-project/
├── src/
│ ├── index.ts <-- TypeScript source
│ └── utils.ts
├── dist/
│ ├── index.js <-- Compiled JavaScript
│ └── utils.js
├── tsconfig.json
└── package.json
Tip: Add
distto your.gitignorefile. You do not need to commit compiled files to Git.
How to Configure include and exclude
These two options sit outside compilerOptions. They control which files TypeScript looks at.
include tells TypeScript which files or folders to compile:
{
"include": ["src", "tests"]
}
exclude tells TypeScript which files or folders to ignore:
{
"exclude": ["node_modules", "dist", "**/*.spec.ts"]
}
By default, TypeScript excludes
node_modulesautomatically. But it is a good habit to list it yourself so nothing surprises you.
How to Set Up Path Aliases with paths
Path aliases let you use short import names instead of long relative paths.
Without aliases, your imports look like this:
import { formatDate } from "../../../utils/formatDate";
With path aliases, the same import looks like this:
import { formatDate } from "@utils/formatDate";
Here is how to set that up in tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@utils/*": ["src/utils/*"],
"@models/*": ["src/models/*"],
"@services/*": ["src/services/*"]
}
}
}
Important:
pathsintsconfig.jsonis only for TypeScript. If you use a bundler (like Webpack or Vite), you need to set up the same aliases in your bundler config too.
How to Add lib for Extra Type Definitions
The lib option tells TypeScript which built-in type definitions to include.
If you are building for browsers, you need the DOM types. If you are building for Node.js, you do not.
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"]
}
}
lib Value |
Includes Types For |
|---|---|
ES2022 |
Modern JavaScript APIs |
DOM |
Browser APIs like document and window
|
DOM.Iterable |
Iterating over DOM collections |
ESNext |
The very latest JS features |
For Node.js projects, skip DOM and just use ["ES2022"].
How to Enable Source Maps for Debugging
Source maps connect your compiled JavaScript back to your original TypeScript code. This makes debugging much easier in tools like VS Code and browser dev tools.
{
"compilerOptions": {
"sourceMap": true
}
}
This creates a .map file next to each compiled .js file. Debuggers use these files to show you the TypeScript line number when something breaks.
Complete tsconfig.json Templates
Here are two ready-to-use configs you can copy.
For a Node.js Project
{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"lib": ["ES2022"],
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"sourceMap": true,
"resolveJsonModule": true,
"declaration": false
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
For a Browser App (with a Bundler like Vite)
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"sourceMap": true,
"moduleResolution": "Bundler",
"resolveJsonModule": true
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
Common Mistakes to Avoid
Here are the most common tsconfig.json mistakes developers make.
-
Not enabling
strict: true-- You will miss many bugs that TypeScript would have caught. -
Wrong
rootDirpath -- If TypeScript cannot find your source files, it will not compile. -
Forgetting to exclude
node_modules-- TypeScript may try to compile third-party packages and throw errors. -
Mismatched
targetandlib-- If yourlibhas features that yourtargetdoes not support, you get errors. -
Using
pathswithoutbaseUrl-- Path aliases do not work unlessbaseUrlis also set.
Quick Reference: Most Used Options
| Option | Recommended Value | Reason |
|---|---|---|
target |
ES2022 |
Modern and stable |
module |
CommonJS (Node) / ESNext (browser) |
Matches your runtime |
strict |
true |
Catch more bugs at compile time |
rootDir |
./src |
Keeps source organized |
outDir |
./dist |
Keeps compiled files separate |
esModuleInterop |
true |
Easier imports from npm packages |
skipLibCheck |
true |
Faster builds |
sourceMap |
true |
Better debugging |
FAQ
Q: Do I need a tsconfig.json file?
Yes. Without it, TypeScript uses defaults that may not match your project. Always create one.
Q: Can I have more than one tsconfig.json?
Yes. Large projects often have multiple config files. You can use extends to share settings between them.
Q: What does skipLibCheck: true do?
It tells TypeScript to skip type checking inside .d.ts files from your node_modules. This speeds up compilation. It is safe to turn on for most projects.
Q: What is the difference between target and lib?
target sets the JavaScript version of your output. lib sets which built-in type definitions TypeScript knows about. They are related but separate.
Q: Should I commit tsconfig.json to Git?
Yes. Always commit tsconfig.json. It is part of your project setup. Do not commit the dist folder.
Q: Why does TypeScript say "rootDir is expected to contain all source files"?
This happens when TypeScript finds a .ts file outside your rootDir. Check if your test files or other config files are placed inside rootDir or adjust your include and rootDir settings.
What You Learned
-
tsconfig.jsonis the config file for TypeScript projects - You create it with
tsc --init -
compilerOptionscontrols how TypeScript compiles your code - Always use
strict: trueto catch more bugs -
rootDirsets where your source files are andoutDirsets where compiled files go - Use
includeandexcludeto control which files TypeScript processes - Path aliases (
paths) make imports cleaner
Sources: TypeScript Official Docs | Total TypeScript TSConfig Cheat Sheet
Top comments (0)