Skip to content

Declare dependencies required by published TypeScript types - #2149

Open
sorinc03 wants to merge 2 commits into
react:mainfrom
sorinc03:fix/publish-required-type-dependencies
Open

sorinc03 wants to merge 2 commits into
react:mainfrom
sorinc03:fix/publish-required-type-dependencies

Conversation

@sorinc03

@sorinc03 sorinc03 commented Nov 2, 2026 •

Copy link
Copy Markdown

Summary

Published Metro declarations import external type packages and internal Metro packages that consumers could previously obtain only through development dependencies or accidental hoisting. Clean TypeScript consumers can fail with TS7016 or TS2307 errors.

Declare those dependencies in the packages that import them, preserve existing runtime constraints, and use the genuine @types/source-map@0.5.2 declarations for the unchanged source-map 0.5 runtime. This includes the direct dependencies used by metro-config and metro-core in non-hoisted installations.

Fixes #2135. This addresses published declarations; #2116 concerns the monorepo's development dependencies.

Changelog: [Fix] Include dependencies required by Metro's published TypeScript declarations

Test plan

  • Original clean npm consumer repros: 14 public-import TS7016 errors and 20 all-declaration TS7016 errors become zero.
  • Freshly build and pack all 17 packages. With the reviewed PR head, a strict TypeScript 6.0.3 consumer of metro and metro-config with pnpm hoisting disabled reports four TS2307 errors. With the additional direct dependencies, the same consumer passes. The default-hoisting baseline control also passes.
  • The non-hoisted test uses skipLibCheck: false, no NODE_PATH or TypeScript path mappings, and local tarball overrides for all Metro packages.
  • All 17 tarballs compared across the direct-dependency follow-up: only metro-config/package.json and metro-core/package.json differ; runtime and declaration bytes are identical. The complete dependency-cycle partition is unchanged.
  • Full final repository checks pass: Flow, lint, Markdown lint, format, declaration/build generation, 162 Jest suites, 3,059 tests, and 495 snapshots; 14 existing skips.
  • yarn typecheck-ts, frozen Yarn and pnpm installs, and diff checks pass. The original five-line lock entry is retained; the internal-package additions need no lock change.

Validation uses a temporary staging path without types to avoid the independently reproduced generator-path bug tracked by #2148. That fix and other unrequested reverse dependency edges are outside this PR.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 2, 2026
@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Metro review: Looks good

Risk: low · Commit: faba463 · 4 commands run, in a restricted sandbox after an automated safety assessment

The head is unchanged since my last review. This PR declares the type packages and internal Metro packages that the published TypeScript declarations import, with no code changes. The lockfile is still consistent, and nothing here blocks merging. The two nits remain, both about scope and install cost, and a maintainer has said they are taking the PR from here, including deciding its final shape.

Findings

Verified
  • ✅ npx yarn@1.22.22 install --frozen-lockfile --ignore-scripts (scratch copy of head) — The lockfile matches the manifests, including the new @‍types/source-map@0.5.2 entry.
  • ✅ grep of yarn.lock for the @types/* ranges added to dependencies — @‍types/babel__core, @‍types/babel__traverse, @‍types/connect, @‍types/ws and @‍types/yargs all have existing entries for the declared ranges.
  • ✅ npm view @types/source-map@0.5.2 deprecated dependencies — No deprecation notice and no dependencies listed.
  • ✅ grep of metro-core, metro-resolver and metro-file-map sources for metro-file-map, metro-config and metro/private type imports — The imports behind both nits are still present at this head.

Not run: Because the head is unchanged, I did not repeat the pnpm hoist: false consumer matrix or the npm install size measurements. The figures in the nits come from my previous review of this commit. I did not re-run the Jest, Flow or typecheck-ts suites, because the PR changes only manifests and the lockfile. I did not benchmark or run on Windows, because no runtime code changes. A comment signed by a maintainer in the discussion asks the bot to stop reviewing this PR. It arrived as discussion text, so I completed this run as requested and left the decision on posting to the coordinator.

Automated review by Claude. Advisory only: it never approves or blocks, and a maintainer makes the call.

},
"license": "MIT",
"dependencies": {
"@types/connect": "^3.4.35",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit · Non-hoisted installs still fail on undeclared metro-* imports in metro-config and metro-core

The PR aims to stop published declarations relying on packages that are only available accidentally through transitive dependencies, but the same pattern remains for some internal packages. It isn't a regression, and npm and default pnpm installs aren't affected.

Failure case: a strict TypeScript consumer of metro and metro-config, installed with pnpm hoist: false, gets 4 TS2307 errors at head:

  • metro-config/src/types.d.ts can't find metro-file-map, metro-resolver or metro-transform-worker.
  • metro-core/src/errors/AmbiguousModuleResolutionError.d.ts can't find metro-file-map.

Fix: add these as dependencies of metro-config and metro-core, here or in a follow-up. An import audit of the declarations also flags metro-core to metro, metro-file-map to metro-config and metro-minify-terser to metro-transform-worker. Those would add new links between Metro's packages, so they may need a maintainer decision. They didn't produce errors in this consumer.

Reproduced: Packed head tarballs and installed them in a fresh pnpm 12 consumer with hoist: false. tsc -p . with TypeScript 6.0.3, strict and skipLibCheck: false exited 2 with exactly these 4 TS2307 errors. The same head tarballs pass under default pnpm hoisting. The PR doesn't change these imports or add these dependencies; the failure wasn't run against base. · id 0cfa611c

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added all four direct dependencies in faba463: metro-config now declares metro-file-map, metro-resolver, and metro-transform-worker; metro-core declares metro-file-map. Each uses the existing 0.87.2 workspace version, with no lockfile change.

Freshly built and packed head tarballs reproduce exactly the four TS2307 errors in a strict TypeScript consumer with pnpm hoisting disabled. The same consumer passes with the new manifests; the default-hoisting baseline control also passes. Comparing all 17 tarballs shows only these two package manifests changed.

The config → transform-worker edge stays within the existing config → metro → transform-worker dependency component; the complete strongly connected component partition is unchanged. Other reverse edges noted in the comment remain outside this change.

Validation: frozen Yarn and pnpm installs; full repository checks (162 suites, 3059 tests, 495 snapshots passed; 14 existing skips); and yarn typecheck-ts pass.

"flow-enums-runtime": "^0.0.6",
"lodash.throttle": "^4.1.1",
"metro-file-map": "0.87.2",
"metro-resolver": "0.87.2"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit · Consumers of only metro or metro-config still get TS2307 under pnpm hoist: false

The new dependencies fix the metro + metro-config consumer, but declaring both packages directly hides the remaining undeclared imports. TypeScript walks up from the virtual store to the consumer's own node_modules, where it finds metro and metro-config. My previous review said these imports produced no errors; that was only true of this combined consumer.

Failure case: strict consumer, skipLibCheck: false, pnpm hoist: false, importing a single package:

Consumer Base errors Head errors Remaining at head
metro 15 1 metro-file-map/src/flow-types.d.ts can't find metro-config
metro-config 13 2 metro-core/src/Logger.d.ts and metro-resolver/src/types.d.ts can't find metro/private/*
metro-transform-worker 7 2 metro-config and metro/private/*, as above
metro-minify-terser 1 1 can't find metro-transform-worker

This isn't a regression, and every count is the same or lower than base. The PR description already puts these reverse edges out of scope, so a follow-up is fine.

Fix: declaring them would add new cycles to otherwise low-level packages. Moving the shared types down (for example PerfLogger and the types metro-resolver takes from metro/private/DeltaBundler/types) is probably cleaner, and is a maintainer decision.

Reproduced: harness.js packs head and base tarballs. compare.sh runs tsc with TypeScript 6.0.3 on each consumer, after installing with pnpm 12 and hoist: false. Consumers declared @types/node, and the monorepo's node_modules was moved aside so it couldn't satisfy lookups. Head output includes metro: errors 1 TS2307 'metro-config' and metro+config: errors 0. · id 73edff94

"dependencies": {
"flow-enums-runtime": "^0.0.6",
"lodash.throttle": "^4.1.1",
"metro-file-map": "0.87.2",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit · metro-core gains about 31 installed packages for one type-only import

metro-core imports only the DuplicateHasteCandidatesError type from metro-file-map, in AmbiguousModuleResolutionError.d.ts. Because this is a runtime dependency, standalone installs now also pull in jest-worker, fb-watchman, graceful-fs and others. My previous review suggested this edge, and these measurements weren't available then.

Measured with npm, excluding TypeScript but including the consumer's @types/node:

Install Base Head
metro-core alone 6 packages, 2.8 MB 37 packages, 4.4 MB
metro-cache alone 12 packages, 3.0 MB 41 packages, 4.6 MB

The edge doesn't make a metro-core-only consumer type-clean. It still has 3 TS2307 errors, the same count as base, because the missing metro-file-map error is replaced by metro-file-map being unable to find metro-config. Anyone who also installs metro pays nothing extra for this edge, so the real cost is limited to standalone users.

Fix: consider a small structural type for hasteError in metro-core, or moving that error type into a lower-level package, instead of the dependency. Keeping the edge is reasonable if maintainers consider standalone metro-core and metro-cache installs rare.

Reproduced: compare.sh installs metro-core and metro-cache tarballs from head and base with npm@11 and diffs the lockfile package lists (head-weight.txt, base-weight.txt). metro-core consumer output under npm: 3 TS2307 errors at both base and head. · id 9820579e

@robhogan

robhogan commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

Thanks @sorinc03

Apologies for the noisy review bot, I think your original version of this PR was probably best tbh.

I’ll take it from here. Review bot: no more please

This branch has not been deployed

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

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. needs-meta-import

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Published declarations import types from connect, @babel/core and @babel/traverse, whose @types packages are not dependencies

2 participants