Skip to content

Watch mode: clean up output files when source files are deleted#2710

Open
DukeDeSouth wants to merge 1 commit intomicrosoft:mainfrom
DukeDeSouth:fix/watch-cleanup-deleted-outputs
Open

Watch mode: clean up output files when source files are deleted#2710
DukeDeSouth wants to merge 1 commit intomicrosoft:mainfrom
DukeDeSouth:fix/watch-cleanup-deleted-outputs

Conversation

@DukeDeSouth
Copy link

@DukeDeSouth DukeDeSouth commented Feb 7, 2026

Human View

Summary

Fixes microsoft/TypeScript#16057 — a 9-year-old bug (154 reactions) where tsc --watch does not delete corresponding output files when a source .ts file is deleted.

Problem

When using tsc --watch, deleting a source .ts file triggers a rebuild, but the corresponding output files (.js, .js.map, .d.ts, .d.ts.map) remain on disk. This causes:

  • Test runners executing stale code
  • Bundlers picking up dead modules
  • Confusing import resolution errors

Solution

The watcher already detects file deletions (in hasBeenModified()), but never cleans up the orphaned outputs. This PR adds a cleanupDeletedOutputs() method that:

  1. Captures deleted source file names in hasBeenModified() by comparing the previous file snapshot against the current state
  2. Computes output paths for each deleted source file using the existing outputpaths package
  3. Removes stale output files via vfs.FS.Remove()

The cleanup handles all output types:

  • .js files
  • .js.map (when sourceMap is enabled)
  • .d.ts (when declaration is enabled)
  • .d.ts.map (when declarationMap is enabled)

It respects outDir, declarationDir, noEmit, and other compiler options.

Changes

File Change
internal/execute/watcher.go Add deletedFiles field, capture deleted files in hasBeenModified(), add cleanupDeletedOutputs() method, call it from DoCycle()
internal/execute/tsctests/tscwatch_test.go Add test case for file deletion cleanup
testdata/baselines/reference/tscWatch/commandLineWatch/watch-cleans-up-deleted-file-outputs.js New baseline

Test

The new test case:

  1. Creates a.ts and b.ts with outDir: "dist"
  2. Initial build emits dist/a.js and dist/b.js
  3. Deletes b.ts
  4. Watch cycle rebuilds → verifies dist/b.js is removed

The baseline confirms the deletion: [/home/src/workspaces/project/dist/b.js] *deleted*

All existing watch mode tests pass without modification.


AI View (DCCE Protocol v1.0)

Metadata

  • Generator: Claude (Anthropic) via Cursor IDE
  • Methodology: AI-assisted development with human oversight and review

AI Contribution Summary

  • Solution design and implementation

Verification Steps Performed

  1. Reproduced the reported issue
  2. Analyzed source code to identify root cause
  3. Implemented and tested the fix

Human Review Guidance

  • Core changes are in: .js.map, .d.ts, .d.ts.map

Made with M7 Cursor

When using `tsc --watch`, deleting a source .ts file did not remove the
corresponding output files (.js, .js.map, .d.ts, .d.ts.map) from the
output directory. This left stale outputs that could be picked up by
test runners, bundlers, and other downstream tools.

The watcher already detected file deletions and triggered rebuilds, but
never cleaned up the orphaned outputs. This change adds a
`cleanupDeletedOutputs` method that:

1. Captures deleted source file names in `hasBeenModified()` by
   comparing the previous file snapshot against the current state.
2. After emit, computes output paths for each deleted source file using
   the existing `outputpaths` package.
3. Removes the stale output files via `vfs.FS.Remove()`.

The cleanup handles all output types: .js, .js.map (sourceMap), .d.ts
(declaration), and .d.ts.map (declarationMap). It respects `outDir`,
`declarationDir`, `noEmit`, and other compiler options.

Fixes microsoft/TypeScript#16057

Co-authored-by: Cursor <cursoragent@cursor.com>
@DukeDeSouth
Copy link
Author

@microsoft-github-policy-service agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Typescript Watch - Cleaning Target Files on Source Deletion

1 participant