TypeScript 4.4.3 closes leaked package metadata watchers
TypeScript 4.4.3 repairs cleanup of package.json file watchers. A build can finish its compiler work yet keep its process alive when those persistent resources remain open.
A build process that remains alive after generating its output may have a resource-lifetime problem rather than unfinished compilation. TypeScript 4.4.3 fixes one such case involving file watchers on package.json. The npm registry records publication on September 10, and the release note identifies the watcher leak as a reason for the patch. The compiler's teardown path had omitted a collection of watchers created for package metadata.
The original report describes builds hanging after moving from 4.3.5 to 4.4.2. Its investigation found persistent watcher handles associated with package files. That observation connects the visible symptom to process lifetime, rather than assuming that a type-checking algorithm was still consuming work.
I consider reliable shutdown part of a build tool's interface. TypeScript's ecosystem often embeds compiler services inside other tools, so a resource that outlives its owner can affect more than a standalone compiler invocation. Producing correct output and releasing the resources used to produce it are separate obligations.
Package resolution creates resources with an owner
The 4.4.3 watch-program source declares packageJsonMap as a map of file watchers for package files used in module resolution. Those entries are not ordinary source-file objects. They maintain observation of metadata that can affect how the program resolves dependencies.
That distinction explains why source-file cleanup alone is insufficient. A watch program can track configuration files and package-resolution inputs in addition to the files whose code it checks. Each watcher still requires a matching release operation when the program closes.
The source's close function already clears several resource collections. It closes source-file watchers and configuration watchers, and handles missing-file and directory-watcher state. The package map needs equivalent treatment even though its entries were created for a different part of resolution.
The reported handles make that omission observable outside the compiler. A persistent watcher can keep a Node process alive while no further compiler operation is expected. A user sees a build that does not terminate, but the retained resource belongs to the tooling implementation underneath it.
Clearing a map is not enough without closing its entries
The fix diff adds a short block to close. If the package map exists, it calls clearMap(packageJsonMap, closeFileWatcher) and then clears the map reference. The callback matters because dropping the collection alone would not express the required watcher-close operation.
The patch therefore repairs ownership cleanup at the point where the watch program releases its other resources. It does not change package selection rules or introduce a new public configuration option. The intended package observations remain available during the program's lifetime, with cleanup when that lifetime ends.
This is a useful way to distinguish a leak fix from disabling useful behavior. Removing watchers entirely might also remove the retained handles, but would change what updates the running program can observe. Closing them at teardown preserves their active role while addressing the lifetime error.
The map reference is also reset after cleanup, consistent with the surrounding teardown code. That expresses that the closed program no longer owns the collection. The meaningful operation is the combination of closing entries and abandoning the container after their resources have been released.
The baselines expose watcher multiplicity
The patch changes watch-test baselines as well as the implementation. Several baselines previously showed duplicate watcher entries for package files after watch-program transitions. The updated expected output removes those extra entries. Other cases remove package watchers that no longer belong in the resulting state.
Those changes make resource state part of the expected behavior. A test that checks only diagnostics or emitted JavaScript could pass while watchers accumulate. Recording the watched files exposes a different property, whether transitions leave the program observing the right collection of files.
This does not establish a universal memory reduction or build-time improvement. The supported conclusion is narrower. The patch closes package metadata watchers that the earlier teardown omitted, and the changed baselines show the resulting watcher collections in specific scenarios.
The original report is likewise evidence about a particular build integration. Its observed persistent handles explain that reproduction, without proving that every project using 4.4.2 would hang. The useful diagnosis connects a concrete retained resource to the failure condition.
I prefer that precision when evaluating maintenance releases. Calling a process hang a performance regression can lead an investigation toward expensive compilation when the process is actually waiting with live handles. Here, the source and the resource report point to cleanup directly.
TypeScript 4.4.3 includes that missing cleanup alongside a separate JavaScript-completion fix named in the release note. For integrations that create and close watch programs, the package metadata map now follows the teardown discipline already applied to other watcher collections. The program releases those watchers instead of leaving their lifetime detached from the compilation that created them.