Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript Watch - Cleaning Target Files on Source Deletion #16057

Open
alohaninja opened this issue May 24, 2017 · 22 comments
Open

Typescript Watch - Cleaning Target Files on Source Deletion #16057

alohaninja opened this issue May 24, 2017 · 22 comments
Assignees
Labels
Bug A bug in TypeScript
Milestone

Comments

@alohaninja
Copy link

Can we add a compiler option to also glob-delete a target file when the source file is removed? We run into this constantly and have to gulp clean frequently - it makes the usage of tsc -watch pointless as we have to constantly purge the output directory.

@mhegazy mhegazy added the Bug A bug in TypeScript label Aug 23, 2017
@mhegazy mhegazy added this to the TypeScript 2.6 milestone Aug 23, 2017
@mhegazy
Copy link
Contributor

mhegazy commented Aug 23, 2017

For tsc --watch we have a list of output files from the previous iteration, we just need to diff that with the current list, and delete the old outputs.

@mhegazy mhegazy modified the milestones: TypeScript 2.6.1, Future Oct 16, 2017
@timm-gs
Copy link

timm-gs commented Nov 14, 2017

Is there a recommended way to work around this today? We have prepended rimraf lib/ to our build scripts, which removes the folder containing the compiled JS files.

But this is caused problems with sym-linked modules. The importing project's watch then gets broken with TS2307: Cannot find module, as it only seem to register the disappearance of the lib folder, but not the new one put in its place.

@admosity
Copy link

Can someone provide some pointers where I can help implement this? @mhegazy?

@mhegazy
Copy link
Contributor

mhegazy commented Mar 29, 2018

Things have gotten a bit more complicated with the addition of the Builder the and the WatchProgram (see #20234), there is not really a place to keep this information, since it is always partial, and we are not rebuilding the information after every change as we used to do. I suppose we could investigate restarting the builder if a file was removed. but we will need a way to detect that in the first place..

@bes
Copy link

bes commented Jan 11, 2019

Hi!

This is constantly biting us during development. A file is removed - but nightwatch / some other library still picks it up and runs tests based on code that should not be there.

Last activity on this was more than 8 months ago, but I hope there is still a possibility for this to be added?

Thanks!

@nullxone
Copy link

If you're using jest, you can use ts-jest

@TarVK
Copy link

TarVK commented May 21, 2019

My 'solution' is obviously not the full thing that is trying to be implemented right now, it's just some very basic behavior I need myself, But I think it might help some people that need something like this right now. So if it's alright, I will just leave a link here for now: https://www.npmjs.com/package/ts-cleaner

@beverts312
Copy link

beverts312 commented Jun 4, 2019

This functionality would also be helpful on a simple --clean, this is effecting us in CI and when switching between branches locally

@insidewhy
Copy link

ts-cleaner didn't work for me, so I wrote ts-purify. It works exactly the same way as ts-cleaner but uses fb-watchman (its only dependency) instead of chokidar. This makes it very small and very efficient at watching, but on the other hand, you'll need to install watchman to use it.

@geremy22
Copy link

geremy22 commented Oct 11, 2019

Hello!!
I solved this issue with watch, diff-file-tree and rimraf:
tsconfig.json

{
  "compileOnSave": false,
  "compilerOptions": {
    "rootDir": "./src",
    "outDir": "./.tmp",
    "preserveSymlinks": true,
    "sourceMap": true,
    "declaration": true,
    "module": "umd",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es6",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es6"
    ]
  },
  "include": [
    "./src/**/*.*"
  ]
}

package.json

{
  "name": "diff-tree",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "tsc && npm run build:copy",
    "build:copy": "node -e \"(d = require('diff-file-tree')).diff('./.tmp', './dist').then((ch)=>d.applyRight('./.tmp', './dist', ch)).finally(()=>process.exit(0));\" && rimraf ./.tmp",
    "watch": "watch \"npm run build\" ./src --interval 1 --wait 0.1"
  },
  "author": "",
  "license": "ISC",
  "devDpendencies": {
    "diff-file-tree": "^2.3.2",
    "rimraf": "^3.0.0",
    "typescript": "^3.6.4",
    "watch": "^1.0.2"
  }
}

@wclr
Copy link

wclr commented Jul 24, 2020

For cleaning up of not actual compilation results I use this https://github.com/whitecolor/ts-clean-built

@simonwep
Copy link

Any update on this one? It's still causing a headache...

@felipeggrod
Copy link

Still causing problems...

@rbrcurtis
Copy link

I would think this feature could use the build info from —incremental to know what needs to be deleted.

@DylanCulfogienis
Copy link

Any updates on this?

@akd-io
Copy link

akd-io commented Jul 29, 2021

Also facing this problem, would be a very nice addition

@theomessin
Copy link

Bump

@WestonThayer
Copy link

Just wanted to add that none of the 3rd party library workarounds mentioned above take care of cleaning up the .tsbuildinfo file. It keeps info about the deleted source file. Probably not a huge deal, but could lead to bloat with large refactors.

@jeremyong
Copy link

For tsc --watch we have a list of output files from the previous iteration, we just need to diff that with the current list, and delete the old outputs.

I found this issue after a bit of searching since this is still a very common source of bugs and poses an unfortunate workflow problem with tsc --watch. In fact, my initial conclusion is that I should be rolling my own watch that invokes tsc -p on individual files that are changed.

My question here is, why would our approach be to maintain a list of files necessarily? The underlying FS watch should receive events on file deletion or move (typically a "rename" event). On rename, we simply check if a corresponding JS file exists in the outDir that matches the file that had moved or been deleted, and delete that JS file. This is a stateless operation and hopefully shouldn't be too hard to implement, but what am I missing? (this is the approach I am going to take when doing this in user space anyways).

@anodynos
Copy link

anodynos commented Feb 16, 2023

This a daunting issue, especially if you refactor often, which you should!

And this, is the story about my pursuit to fixing it, the 2023 way! Of course with the help of AI, ChatGTP in particular. So keep reading...

Initially, I googled the issue with "typescript tsc watch remove deleted files", which is how we used to trouble shoot always. Google responded with current issue first, which was frustratingly still open after 6 years (!).

I followed more links but none seemed like solving the problem inherently:

Google results

Reading the current issue, I found ts-clean-built to be the best solution & project around at this time. Before even giving it a spin, with only issue, it seemed it would save me hours of wasted effort ;-)

But don't we all have ChatGPT plugins right now, next to the google search? It's just a click away, or as a paid customer you get ALWAYS ChatGPT's answer. Which read as:

ChatGPT
When using tsc with the --watch flag, it will recompile the files every time there is a change in the project directory. However, by default, tsc doesn't remove files that have been deleted from the project directory. To remove the deleted files from the output directory, you can use the --removeComments flag.

Here's an example command that uses both --watch and --removeComments:

tsc --watch --removeComments
The --removeComments flag removes all comments from the output files and also removes any files that no longer exist in the source directory.

If you want to keep comments in the output files, you can use the --clean flag instead, which removes any files that no longer exist in the source directory without removing comments:

tsc --watch --clean
Note that if you are using a version of tsc older than 3.8, the --removeComments flag will not work as intended. Instead, you can use the --preserveWatchOutput flag, which will also remove deleted files:

tsc --watch --preserveWatchOutput
Keep in mind that this flag is only available in TypeScript version 3.8 and newer.

Wow! Is that true? Did Chat GPT overwhelmingly solved my ;issue with one --clean commmand, but googled failed to tell me?

So I immediately added the --clean flag to my scripts: npx tsc --watch --clean -p tsconfig.json. Of course it failed:

error TS5093: Compiler option '--clean' may only be used with '--build'.

ChatGPT let down No 1. For a start, --clean can be used only along side --build for some reason something ChatGPT could and maybe should have known! Not sure about the dates tho.

So, lets try again:

npx tsc --clean --watch --build -p tsconfig.json

And this time I get:

ERROR: "error TS6369: Option '--build' must be the first command line argument.

Why so stringent? Another try...

npx tsc --build --clean --watch -p tsconfig.json

Guess what! Two errors this time!

error TS5072: Unknown build option '-p'.

error TS6370: Options 'clean' and 'watch' cannot be combined.

Ok, I had enough! In any case, --build --clean are useless when watching, its doesnt "mirror" src/ to dist/ amd has a myriad of issues - see https://stackoverflow.com/questions/68144771/whats-the-difference-between-tsc-build-clean-vs-rm-rf-js

So I tried on last thing, although I was sure its doomed. According to ChatGPT The --removeComments flag removes all comments from the output files and also removes any files that no longer exist in the source directory.. Lets see:

tsc --watch --removeComments

As one would expect, it doesn't, it is just to Disable emitting comments..

So ChatGPT lied and tried to fool me twice in one problem, as many as the solutions! Welcome to the Brave New World of lies, AI powered!

TypeScript team, please, please solve this issue! Till then I'm going for ts-clean-built!

@alexandrubau
Copy link

alexandrubau commented Feb 15, 2024

To anyone looking for a solution, I've completely stopped using tsc --watch and instead relied on chokidar-cli for watching over my files and triggering the tsc build command.

I don't know if it is as efficient as tsc --watch command but at least it works.

{
  "name": "myproject",
  "scripts": {
    "watch": "chokidar \"src/*\" \"tsconfig.json\" -c \"npm run build\" --initial",
    "build": "rimraf dist && tsc"
  },
  "devDependencies": {
    "@types/node": "^20.11.17",
    "chokidar-cli": "^3.0.0",
    "rimraf": "^5.0.5",
    "typescript": "^5.3.3"
  }
}

@Crestanzio
Copy link

For anyone have this problem like me, i have made a library to solve this, and many more, take a look. typemon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript
Projects
None yet
Development

No branches or pull requests