fix(check): load a single @types/node#35641
Merged
Merged
Conversation
When a project provides its own @types/node, the type-checker loaded both it and the built-in copy, so with a single global symbol table every node declaration is duplicated. Resolve the user's @types/node once and reference the resolved file directly from lib.node.d.ts (so exactly one copy is in the program), falling back to the built-in when the user has none. The resolved path is referenced directly rather than re-emitting `types="npm:@types/node"`, which would be re-resolved relative to the asset file and fail for cache-only / frozen installs.
This was referenced Jun 30, 2026
bartlomieju
added a commit
that referenced
this pull request
Jul 8, 2026
This drops Deno's forked TypeScript compiler and runs on stock `[email protected]` from npm (the exact version the fork was based on). The forked `cli/tsc/00_typescript.js` and its ~466-line patch set are removed, along with the five `ts.deno.*` host hooks the fork exposed (`setIsNodeSourceFileCallback`, `setNodeOnlyGlobalNames`, `setTypesNodeIgnorableNames`, and the LSP span callbacks). Forking tsc has meant a manual re-port of the patch set and a hand-rebuilt 9 MB bundle on every upgrade; on stock TypeScript an upgrade becomes a version bump. The fork's load-bearing patch was a dual node/deno global symbol table in the checker. That is replaced by a pure `.d.ts` mechanism: Deno's libs declare the marker globals (`onmessage`/`onabort`/`ReportingObserver`) that stock `@types/node` probes for, so `@types/node` defers its web-platform globals to Deno's exactly as it defers to `lib.dom`, and everything resolves against a single global table. This builds on the prep PRs already merged: the deferral transform (#35639), the `PerformanceObserver` types (#35640), and single `@types/node` loading (#35641). It also carries the `URLPattern` concession (`@types/node` declares it unconditionally, so Deno keeps only the interface) and tightens `import.meta.dirname`/`filename` to required `string` to match `@types/node`. This is a breaking change and targets Deno 3. Five `check` specs are temporarily disabled with `ignore: true` and a comment pointing at their follow-ups: `check_workspace` and the marker interaction, the `export =` declaration-file case, per-member `jsxImportSource` (`jsx_import_source_different_per_member`), and transitive `@types/node` (`express_with_koa`, re-enabled by #35871). The LSP runs on the same stock compiler; its dedicated verification is still pending. See #35621 for the full investigation and plan. Fixes #33012
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When a project provides its own
@types/node, the type-checker loaded itand the built-in copy that backs
lib="node". With a single global symboltable that means every node declaration (
process,Buffer,node:path, theServer/Console/ etc. types) is declared twice. The current forkedcompiler hides this with its dual node/deno global tables, but it's a latent
double-load and a blocker for moving to a single global table.
This resolves the user's
@types/nodeonce (from the project) and referencesthe resolved file directly from
lib.node.d.ts, so exactly one copy ends up inthe program. When the project has no
@types/node, the built-in copy is servedas before, so the default experience is unchanged.
The resolved path is referenced directly instead of re-emitting
/// <reference types="npm:@types/node" />, because the latter would bere-resolved relative to the
asset:///lib.node.d.tsfile rather than theproject, which fails for cache-only /
--frozeninstalls (the package is knownfrom the lockfile but not under
node_modules).Part of the broader effort to drop Deno's forked TypeScript; see #35621 for context and the overall plan.