tsconfig.json tells TypeScript which files belong to a project and how the compiler should check or emit code. Most real TypeScript projects have one because compiler behavior should be consistent for every developer and every build.
Without a config file, you can compile individual files manually, but that does not scale well. A project config lets you define strictness, module behavior, output folders, included files, path aliases, library types, and framework-specific settings in one place.
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"strict": true,
"moduleResolution": "Bundler",
"noEmit": true
},
"include": ["src"]
}
The fastest way to create a starting config is npx tsc --init. It creates a tsconfig.json file with many available options shown as comments or defaults, depending on your TypeScript version.
After generating it, simplify the file to the options your project actually needs. A smaller config is easier for a team to understand.
| Command | Purpose |
|---|---|
npx tsc --init | Create a new tsconfig file. |
npx tsc | Type-check or compile the project using the config. |
npx tsc --showConfig | Show the final resolved compiler configuration. |
npx tsc --init
npx tsc --showConfig
Compiler options decide how strict TypeScript should be, which JavaScript features are expected, how modules are resolved, and whether files are emitted. You do not need to memorize every option, but you should understand the ones that appear in most projects.
| Option | Meaning | Typical Use |
|---|---|---|
target | JavaScript version to output or type-check against | Use modern targets such as ES2020 or ES2022 for current runtimes |
module | Module format such as ESNext or CommonJS | Use ESNext for modern bundlers, CommonJS for older Node setups |
strict | Turns on the main strict checking options | Recommended for new projects |
moduleResolution | How imports are resolved | Bundler for Vite/Next-style apps, NodeNext for modern Node packages |
noEmit | Check types but do not write JS output | Common when a framework or bundler emits code |
outDir | Folder where compiled files are written | Useful for plain Node projects |
rootDir | Source folder used as output root | Often src when output goes to dist |
include | Files or folders TypeScript should include | Keeps the project scope clear |
New projects should usually enable strict. It makes TypeScript much more helpful by preventing implicit any, unsafe null usage, weak assumptions about class properties, and unsafe function assignments.
Strict mode can feel demanding at first, but it teaches better habits quickly. It also catches exactly the kind of bugs that often appear later as undefined values, bad function calls, or incomplete objects.
Use noEmit when TypeScript should only check types and another tool handles output. This is common in Vite, Next.js, React, Vue, and many frontend projects.
Use outDir when TypeScript itself should write JavaScript files. This is common in simple Node.js projects, command-line tools, and backend projects that compile from src to dist.
| Setting | What Happens |
|---|---|
"noEmit": true | TypeScript checks code but does not write JavaScript files. |
"outDir": "dist" | TypeScript writes compiled files into the dist folder. |
| Both together | Usually not useful because noEmit prevents output. |
{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"rootDir": "src",
"outDir": "dist",
"strict": true
},
"include": ["src"]
}
include defines the folders or file patterns TypeScript should load. Most projects include src. exclude removes folders from that set, such as build output or generated files.
files is more exact: it lists specific files one by one. It is rarely needed for normal app projects but can be useful for tiny packages or special build configs.
{
"compilerOptions": {
"strict": true,
"noEmit": true
},
"include": ["src/**/*.ts"],
"exclude": ["dist", "node_modules"]
}
Path aliases let you replace long relative imports with stable project-based imports. Instead of writing ../../../services/userService, you can write something like @/services/userService.
Aliases must be understood by TypeScript and by the tool that runs or bundles your code. In frontend projects, configure the bundler too. In Node.js projects, make sure runtime resolution supports the alias.
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@/components/*": ["src/components/*"]
}
}
}
If a framework creates tsconfig files for you, start with its defaults. Framework templates often include settings required by their build system. Change settings gradually and understand why each change is needed.
For libraries, declaration files may matter because consumers need type information. For apps using Vite or Next.js, noEmit is common because the framework handles bundling. For Node services, compiling from src to dist is still a clear and practical setup.
tsconfig.json defines project-wide TypeScript behavior.
strict is recommended for new projects because it catches important bugs early.
noEmit is common when a bundler handles output; outDir is used when TypeScript emits JavaScript.
include and exclude control which files belong to the project.
Explore 500+ free tutorials across 20+ languages and frameworks.