Question
Fix “Would Overwrite Input File” in TypeScript
Question
In a TypeScript 2.2.1 project using Visual Studio 2015 Update 3, the Error List shows many messages similar to the following:
Cannot write file 'C:/{{my-project}}/node_modules/buffer-shims/index.js' because it would overwrite input file.
The project still builds and runs, but these messages make it difficult to find genuine errors. Given this tsconfig.json configuration, how can these errors be removed?
{
"compileOnSave": true,
"compilerOptions": {
"baseUrl": ".",
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"sourceMap": true,
"target": "ES5",
"forceConsistentCasingInFileNames": true,
"strictNullChecks": true,
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"typeRoots": [],
"types": []
},
"exclude": ["node_modules"]
}
Short Answer
You will learn why TypeScript refuses to emit a file over a file it is already reading, why exclude is not always enough, and how to keep source files, dependencies, and generated JavaScript separate.
Concept
TypeScript has two important jobs:
- It builds a program by finding source files and resolving imports.
- It emits JavaScript, source maps, and declaration files.
The error appears when TypeScript calculates an output path that is also an input path:
input: node_modules/package/index.js
output: node_modules/package/index.js
Overwriting an input file during compilation could destroy a dependency or make the compiler's results unreliable, so TypeScript stops and reports the conflict.
This commonly happens when JavaScript files are included as compiler inputs, usually because allowJs is enabled somewhere or because an editor/project integration includes JavaScript files. If there is no outDir, TypeScript normally emits output next to its source files. That is unsafe for .js input files because their emitted JavaScript path is the same path.
exclude helps control automatic root-file discovery, but it is not an absolute firewall. A file can still enter the program through imports, project tooling, or explicit file lists. A reliable setup explicitly includes the application's TypeScript source directory and emits generated files into a separate output directory.
Mental Model
Think of TypeScript as a printing machine.
- Your source files are the documents fed into the machine.
- Your
node_modulesdirectory is a shelf of reference books. - Emitted JavaScript is the printed result.
If the printer is told to print directly onto a reference book that it is currently reading, it refuses. The solution is to print into a dedicated output tray such as dist, while keeping dependencies on their own shelf.
Syntax and Examples
A typical TypeScript project keeps application code in src and compiled files in dist:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"outDir": "./dist",
"sourceMap": true,
"allowJs": false
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
Key settings:
Step by Step Execution
Consider this configuration:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"outDir": "dist",
"allowJs": false
},
"include": ["src/**/*.ts"]
}
And this source file:
// src/greeting.ts
const message = "Hello, TypeScript";
console.log(message);
When tsc runs:
- It reads
tsconfig.json. includefinds .
Real World Use Cases
Separate input and output directories are useful in nearly every TypeScript application:
- Node.js services: compile
src/server.tstodist/server.js, then runnode dist/server.js. - CLI tools: keep source in
src, publish only the generated JavaScript and required package files. - Frontend applications: let a bundler handle final browser assets while TypeScript writes intermediate output to a build directory, or use
noEmitwhen the bundler performs transpilation. - Monorepos: each package can use its own
srcanddistfolders, avoiding output collisions between packages. - Libraries: emit JavaScript and
.d.tsdeclaration files todistwithout modifying package dependencies.
Real Codebase Usage
In real projects, developers usually define a clear boundary between authored files and generated files.
A common layout is:
project/
src/ # TypeScript written by the team
dist/ # generated JavaScript; usually ignored by Git
node_modules/ # installed dependencies
tsconfig.json
A practical configuration might be:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"outDir": "dist",
"rootDir": "src",
"sourceMap": true,
"strict": true,
"allowJs": false
},
"include":
Common Mistakes
Relying only on exclude
{
"exclude": ["node_modules"]
}
This is helpful, but it does not guarantee that no dependency file will ever be resolved through an import or added by external tooling. Add a focused include list for your application code.
{
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
Emitting next to source files accidentally
Without outDir, TypeScript usually writes output beside each input .ts file. This can clutter source folders and increases the chance of path conflicts in mixed JavaScript/TypeScript projects.
Use a dedicated output directory:
Comparisons
| Setting or approach | What it controls | Does it prevent output collisions by itself? |
|---|---|---|
exclude | Files skipped during automatic root-file discovery | No; imports and tooling can still add files |
include | Files intended to be root inputs | Helps greatly by limiting the project scope |
outDir | Where emitted files are written | Yes, when it is separate from inputs |
allowJs: false | Whether .js files are accepted as inputs | Helps when the unwanted inputs are JavaScript files |
noEmit: true | Whether TypeScript writes output at all | Yes; no files are emitted |
include and answer, “What source files should this project start with?” answers, “Where should generated files go?” They solve related but different problems.
Cheat Sheet
{
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"allowJs": false
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
- Overwrite input file means an emitted file path matches a compiler input path.
- Use
outDirto separate generated JavaScript from source and dependencies. - Use
includeto define the application's source boundary. - Use
excludeto avoid automatic discovery of dependency and build directories. excludedoes necessarily block files reached through imports or external project tooling.
FAQ
Why does TypeScript say it would overwrite an input file?
It is about to write an output file at a path that it is already using as an input. TypeScript blocks the write to avoid replacing source or dependency files.
Why is node_modules involved even though it is excluded?
exclude affects automatic discovery. Dependencies can still be reached during module resolution, or a project/editor integration may include files differently. Restrict include and use a separate outDir.
Does outDir fix this error?
Usually, yes. It gives emitted files a different destination, such as dist, rather than writing beside inputs.
Should I delete node_modules to fix the problem?
No. Deleting and reinstalling dependencies may temporarily change symptoms but does not fix an incorrect input/output configuration.
Should I set allowJs to false?
Yes, if the project is intended to compile TypeScript only. If you are intentionally migrating JavaScript, keep allowJs only with a well-defined include list and outDir.
What does do?
Mini Project
Description
Configure a small Node.js TypeScript project so its source stays in src, installed packages remain untouched in node_modules, and compiled JavaScript is written to dist. This demonstrates the directory separation that prevents overwrite-input errors.
Goal
Compile a TypeScript greeting script to dist/greeting.js without compiling or overwriting dependency files.
Requirements
Create a src/greeting.ts file that prints a greeting.
Configure TypeScript to compile only .ts files under src.
Write generated JavaScript to a dist directory.
Ensure JavaScript files are not accepted as compiler inputs.
Exclude node_modules and dist from automatic discovery.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Accessing Input Value from EventTarget in TypeScript
Learn why EventTarget has no value property in TypeScript and safely read values from HTML input events in Angular applications.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.