How to fix 'rootDir' should not contain 'outDir' in TypeScript
This TypeScript configuration error occurs when your output directory (outDir) is nested inside your source root directory (rootDir), which would cause compiled files to overwrite source files. The fix involves adjusting your tsconfig.json to ensure outDir is outside rootDir or using separate directories for source and compiled code.
Quick fix
Fixes 'rootDir' should not contain 'outDir'
{
"compilerOptions": {
// Problematic configuration example:
"rootDir": "./src",
"outDir": "./src/dist", // ❌ outDir is inside rootDir
// Other common problematic patterns:
// "rootDir": ".",
// "outDir": "./dist", // ❌ If rootDir is current directory
// "rootDir": "./",
// "outDir": "./build" // ❌ Same issue
}
}- Check your current tsconfig.json configuration
- Move outDir outside of rootDir
- Adjust rootDir to be more specific
- Use composite projects for complex setups
{"compilerOptions": {// Problematic configuration example:"rootDir": "./src","outDir": "./src/dist", // ❌ outDir is inside rootDir// Other common problematic patterns:// "rootDir": ".",// "outDir": "./dist", // ❌ If rootDir is current directory// "rootDir": "./",// "outDir": "./build" // ❌ Same issue}}'rootDir' should not contain 'outDir'
What this error means
The "rootDir should not contain outDir" error is a TypeScript compiler safeguard that prevents you from accidentally configuring your project in a way that would cause compiled JavaScript files to overwrite your TypeScript source files. When you set rootDir in tsconfig.json, you're telling TypeScript: "All my source TypeScript files are somewhere under this directory." When you set outDir, you're saying: "Put all my compiled JavaScript files in this directory." If outDir is inside rootDir, then TypeScript would be writing compiled .js files into the same directory tree as your .ts source files. This creates several problems: 1. **File conflicts**: A file like src/app.ts would compile to src/app.js, potentially overwriting other files 2. **Circular compilation**: TypeScript might re-compile its own output files 3. **Clean separation**: Source and compiled files should be kept separate for clarity and build system efficiency TypeScript prevents this configuration to protect your source code and ensure predictable build outputs.
Typical symptoms
- TypeScript compilation fails with error: 'rootDir' should not contain 'outDir'
- Build process stops with configuration error
- IDE shows configuration error in tsconfig.json
- npm run build or tsc command fails immediately
- Continuous integration pipelines fail during TypeScript compilation
Common causes
- outDir path is set to a subdirectory of rootDir (e.g., rootDir: 'src', outDir: 'src/dist')
- Relative path calculations result in nested directories
- Copying tsconfig.json from another project without adjusting paths
- Monorepo configuration where rootDir and outDir overlap
- Using path aliases or baseUrl that create directory conflicts
- Configuration designed for different build tools (like webpack) that doesn't work with tsc
How to fix "'rootDir' should not contain 'outDir'"
First, examine your tsconfig.json to understand the current rootDir and outDir settings:
{
"compilerOptions": {
// Problematic configuration example:
"rootDir": "./src",
"outDir": "./src/dist", // ❌ outDir is inside rootDir
// Other common problematic patterns:
// "rootDir": ".",
// "outDir": "./dist", // ❌ If rootDir is current directory
// "rootDir": "./",
// "outDir": "./build" // ❌ Same issue
}
}Identify the exact paths. The error occurs when outDir is a subdirectory of rootDir.
The simplest fix is to change outDir to be outside your source directory:
{
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist", // ✅ Now outside src directory
// Alternative: Use a sibling directory
// "outDir": "./build",
// Alternative: Use absolute path
// "outDir": "/path/to/project/dist"
}
}Common safe patterns:
- "rootDir": "./src", "outDir": "./dist"
- "rootDir": "./lib", "outDir": "./build"
- "rootDir": ".", "outDir": "../dist" (if you want output in parent directory)
Make sure the outDir directory exists or TypeScript will create it.
If you need to keep your current outDir location, make rootDir more specific to exclude it:
{
"compilerOptions": {
// Before: too broad
"rootDir": ".",
"outDir": "./dist",
// After: specify exact source directories
"rootDir": "./src",
"outDir": "./dist",
// Include only source directories
"include": ["src/**/*"],
"exclude": ["dist", "node_modules"]
}
}You can also use multiple rootDirs if you have source code in different locations:
{
"compilerOptions": {
// Don't set rootDir at all if you have multiple source roots
// TypeScript will infer from include patterns
"outDir": "./dist"
},
"include": ["src/**/*", "lib/**/*", "shared/**/*"]
}When rootDir is not specified, TypeScript calculates it from your include patterns.
For monorepos or complex project structures, use TypeScript project references:
// tsconfig.json (root)
{
"references": [
{ "path": "./packages/core" },
{ "path": "./packages/ui" },
{ "path": "./packages/utils" }
],
"files": [],
"include": []
}
// packages/core/tsconfig.json
{
"compilerOptions": {
"rootDir": ".",
"outDir": "../../dist/core",
"composite": true
},
"include": ["src/**/*"]
}
// packages/ui/tsconfig.json
{
"compilerOptions": {
"rootDir": ".",
"outDir": "../../dist/ui",
"composite": true
},
"include": ["src/**/*"]
}Build with:
npx tsc --buildThis allows each package to have its own rootDir/outDir configuration without conflicts.
After fixing tsconfig.json, clean any previous build artifacts:
# Remove old compiled files
rm -rf dist
rm -rf build
rm -rf out
# Clear TypeScript cache
rm -rf node_modules/.cache
# Rebuild
npx tsc
# Or if using npm scripts
npm run buildIf using an IDE like VS Code, restart the TypeScript server:
1. Press Cmd/Ctrl + Shift + P
2. Type "TypeScript: Restart TS Server"
3. Select the command
Verify the build works:
# Check if files are compiled correctly
ls dist/
# Should see .js files, not .ts filesEnsure your .gitignore properly excludes build directories to prevent committing compiled files:
# .gitignore
dist/
build/
out/
*.js
*.js.map
*.d.ts
# Except if you need declaration files in source control
# !src/**/*.d.ts
node_modules/
.cache/Also update your .eslintignore if using ESLint:
# .eslintignore
dist/
build/
out/
node_modules/For monorepos using workspaces:
# .gitignore for monorepo
packages/*/dist/
packages/*/build/
packages/*/node_modules/Advanced notes
### Understanding rootDir Inference
When you don't specify rootDir explicitly, TypeScript infers it from your include patterns. The inferred rootDir is the longest common path prefix of all input files.
Example:
- Files: src/app.ts, src/utils/helper.ts, src/components/Button.tsx
- Inferred rootDir: src/
If you have files in multiple unrelated directories:
- Files: client/src/app.ts, server/src/index.ts, shared/utils.ts
- Inferred rootDir: . (current directory)
This inference can sometimes lead to the "rootDir should not contain outDir" error if your outDir happens to be inside the inferred rootDir.
### outDir Behavior with Multiple rootDirs
TypeScript doesn't support multiple rootDirs in the compilerOptions. However, you can achieve similar results:
1. Using include/exclude patterns:
{
"compilerOptions": {
"outDir": "./dist"
},
"include": ["src/**/*", "lib/**/*"],
"exclude": ["dist", "node_modules"]
}2. Using project references (as shown in Step 4)
3. Using path mapping with baseUrl:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@src/*": ["src/*"],
"@lib/*": ["lib/*"]
},
"outDir": "./dist"
}
}### Build Tools Integration
Different build tools handle rootDir/outDir differently:
Webpack with ts-loader:
- ts-loader often doesn't use outDir (it pipes to webpack's output)
- You might not need outDir at all
- Configuration example:
{
"compilerOptions": {
"rootDir": "./src",
// No outDir needed for webpack
"module": "esnext",
"target": "es2015"
}
}Vite:
- Uses esbuild for transpilation
- Typically doesn't use tsc's outDir
- Output directory controlled by vite.config.ts
tsc only (no bundler):
- Requires proper rootDir/outDir configuration
- Use for library publishing or Node.js applications
### Common Pitfalls with Monorepos
In monorepos, watch out for:
1. Nested node_modules: If using workspaces, node_modules might be in parent directory
2. Relative path confusion: ../../dist might point to wrong location
3. Shared tsconfig.json: Base config might not work for all packages
Solution: Use extends with package-specific overrides:
// packages/core/tsconfig.json
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": ".",
"outDir": "../../dist/core"
}
}### Debugging Configuration
To debug rootDir/outDir issues:
# Show compiler settings
npx tsc --showConfig
# Dry run to see what would be compiled
npx tsc --listFiles
# Verbose output
npx tsc --verboseCheck which files TypeScript considers as input and where it plans to output them.
Frequently asked questions
- What does "'rootDir' should not contain 'outDir'" mean?
- The "rootDir should not contain outDir" error is a TypeScript compiler safeguard that prevents you from accidentally configuring your project in a way that would cause compiled JavaScript files to overwrite your TypeScript source files. ts source files. This creates several problems: 1.
- How do I fix "'rootDir' should not contain 'outDir'"?
- This TypeScript configuration error occurs when your output directory (outDir) is nested inside your source root directory (rootDir), which would cause compiled files to overwrite source files. The fix involves adjusting your tsconfig.json to ensure outDir is outside rootDir or using separate directories for source and compiled code.
- What causes "'rootDir' should not contain 'outDir'"?
- outDir path is set to a subdirectory of rootDir (e.g., rootDir: 'src', outDir: 'src/dist') Relative path calculations result in nested directories Copying tsconfig.json from another project without adjusting paths
- Is the "'rootDir' should not contain 'outDir'" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- 📚TypeScript Official Documentation
- 📖TypeScript TSConfig - rootDir(Official Docs)
- 📖TypeScript TSConfig - outDir(Official Docs)
- 📖TypeScript Handbook - tsconfig.json(Official Docs)
- 🐙