Skip to content

[api-extractor] Upgrade bundled TypeScript to 6.0.x#5841

Open
hl662 wants to merge 5 commits into
microsoft:mainfrom
hl662:api-extractor-typescript-6
Open

[api-extractor] Upgrade bundled TypeScript to 6.0.x#5841
hl662 wants to merge 5 commits into
microsoft:mainfrom
hl662:api-extractor-typescript-6

Conversation

@hl662

@hl662 hl662 commented Jun 20, 2026

Copy link
Copy Markdown

Summary

Upgrades @microsoft/api-extractor's bundled TypeScript compiler from 5.9.3 to 6.0.3. api-extractor bundles a pinned compiler because it relies on undocumented compiler internals, so the version is advanced and re-validated deliberately each release rather than floated.

Picking up where #5793 left off (it hit CI problems), the bump surfaced two compatibility issues in this repo's own projects, both fixed here:

  • playwright-browser-tunnel — the 6.0 compiler reports TS1540 for the legacy module Foo {} keyword in playwright-core@1.56.1's protocol.d.ts; since api-extractor treats warnings as errors in production, this broke the build. Fixed upstream in Playwright 1.58 (fix: address TypeScript 6.0 deprecations playwright#38558), so this PR bumps the pinned Playwright to 1.58.2.
  • mcp-server — TS 6.0 flips the default CommonJS moduleResolution from node10 to bundler (Deprecate --moduleResolution node10 TypeScript#62338), under which the project's extensionless @modelcontextprotocol/sdk imports stop resolving (TS2307) — and one even fails at runtime under Node (MODULE_NOT_FOUND). Fixed by giving those imports the explicit .js extensions the SDK's exports map requires.

While here, I added the first TypeScriptInternals unit test (and removed a dead getDiagnosticsProducingTypeChecker branch) ahead of TS 7, plus apps/api-extractor/UPGRADING.md so downstream consumers hitting the same resolution change have a documented path — including the compiler.overrideTsconfig escape hatch.

Refs #5052, #5319. Supersedes #5793.

Happy to split the cleanup/test or the migration doc into a separate PR if you'd prefer — and to take this to the finish line with reviews.

Details

1. Upgrade the bundled compiler (+ a small cleanup)

  • Pinned typescript to 6.0.3 in apps/api-extractor/package.json; added 6.0.3 to the typescript allowed-alternatives in common-versions.json (kept 5.9.3, still required transitively by the published @microsoft/api-extractor); regenerated lockfiles / repo-state.json.
  • Validated each (ts as any) internals shim in TypeScriptInternals.ts against the v6.0.3 source, refreshed the source-pointer comments, and removed the dead getDiagnosticsProducingTypeChecker branch (it was removed from the compiler in 4.7; the existing ?? getTypeChecker fallback already covered it). Other shims unchanged.
  • Added the first unit test for TypeScriptInternals (pins the getTypeChecker → getEmitResolver → hasGlobalName chain), which can grow ahead of TS 7.

2. Bump Playwright to 1.58.2 (TS 6.0 compatibility)

  • Upgraded playwright, playwright-core, @playwright/test from 1.56.1 to 1.58.2 in playwright-browser-tunnel and the playwright-local-browser-server VS Code extension, picking up fix: address TypeScript 6.0 deprecations playwright#38558 (converts protocol.d.ts from the legacy module keyword to namespace).

3. Fix @rushstack/mcp-server's SDK imports (TS 6.0 compatibility)

  • @modelcontextprotocol/sdk@1.10.2 exposes its subpath typings only via typesVersions, behind an exports map with no types condition. Under the bundler default the extensionless specifiers don't resolve (the .js-suffixed ones already do), and Node won't extension-complete an exports target either — hence the runtime MODULE_NOT_FOUND. Adding .js is the specifier form the exports map requires; no compiler-option changes to the project.
  • This supersedes an earlier moduleResolution: node10 pin — node10 is deprecated in 6.0 / removed in 7.0, so .js is the forward-compatible choice. (The upstream gap is fixed in @modelcontextprotocol/sdk@1.29.0, which adds types conditions; bumping the SDK is an alternative but a much larger version jump.)

4. Document the resolution change for consumers

  • New apps/api-extractor/UPGRADING.md covering the bundled-compiler moduleResolution default change and the compiler.overrideTsconfig workaround; linked from README.md, published via .npmignore, and referenced from the CHANGELOG entry.
How it was tested

All results from local runs (Node 24.14.0); CI re-verifies.

  • rush rebuild --to @microsoft/api-extractor builds clean against the 6.0 typings; rush test --to @microsoft/api-extractor passes (incl. the new TypeScriptInternals test).
  • Playwright: rush rebuild --to @rushstack/playwright-browser-tunnel --production (CI's mode) failed on the TS bump alone with 126 TS1540 diagnostics from playwright-core@1.56.1; after the 1.58.2 bump it builds clean (0 TS1540). The VS Code extension also builds clean under --production.
  • mcp-server: under the bump, rush rebuild --to @rushstack/mcp-server --production failed with TS2307; with the .js-import fix it builds clean (0 TS2307). Separately confirmed the extensionless value import failed at runtime under Node (MODULE_NOT_FOUND) and resolves with .js. The .api.md golden updates by one line (the import specifier). Also confirmed the compiler.overrideTsconfig escape hatch from UPGRADING.md works on mcp-server (node10 scoped to analysis, build tsconfig untouched — builds clean).
  • api-extractor build-test etc/ snapshots are unchanged.
  • Full-repo rush rebuild --production: the only failure is localization-plugin-test-03 (build), unrelated to this PR — untouched here, present on main, and reproduces only on my machine (main's CI is green).

Impacted documentation

Adds apps/api-extractor/UPGRADING.md (linked from the README and CHANGELOG) documenting the TS 6.0 moduleResolution default change and the compiler.overrideTsconfig workaround for downstream consumers.

hl662 added 2 commits June 20, 2026 11:33
Bump the bundled compiler from 5.9.3 to 6.0.3. The 6.0 compiler
produces byte-identical api-extractor output, so no golden snapshots
changed.

- pin typescript 5.9.3 -> 6.0.3 in apps/api-extractor
- add 6.0.3 to common-versions allowed alternatives (keep 5.9.3, still
  required by the published @microsoft/api-extractor pulled in
  transitively)
- retarget TypeScriptInternals source-pointer comments to the v6.0.3 tag
- regenerate lockfiles / repo-state for the default and
  build-tests subspaces

Internals validated against v6.0.3: getDiagnosticsProducingTypeChecker
was removed but the existing getTypeChecker fallback handles it; all
other shims unchanged. The TS1540 grammar diagnostic that broke microsoft#5793
does not appear in this repo's build-tests graph.

While here (Boy Scout cleanup, motivated by the internals review):
- remove the dead `getDiagnosticsProducingTypeChecker ?? getTypeChecker`
  branch in getGlobalVariableAnalyzer. That API was removed from the
  compiler in TypeScript 4.7 when the dual type-checker was unified, so
  the fallback has been dead since api-extractor bundled 4.7+; simplify
  to the public Program.getTypeChecker(). Behavior-preserving.
- add TypeScriptInternals.test.ts, a regression test that pins the
  getTypeChecker -> getEmitResolver -> hasGlobalName internal chain
  (catches silent semantic drift on a future compiler bump, which the
  existence-only InternalError guards do not).

Refs microsoft#5052, microsoft#5319. Supersedes microsoft#5793.
…Script 6.0 compatibility

The TypeScript 6.0 compiler now bundled by API Extractor reports the TS1540
grammar error for the legacy `module` namespace keyword, which playwright-core's
protocol.d.ts used through 1.56.1.  Playwright converted those declarations to
`namespace` in 1.58 (microsoft/playwright#38558), so without this bump, running
API Extractor over @rushstack/playwright-browser-tunnel fails the production build.

Upgrade playwright, playwright-core, and @playwright/test to 1.58.2 across the
playwright-browser-tunnel app and the playwright-local-browser-server VS Code
extension.
@hl662

hl662 commented Jun 20, 2026

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

@hl662 hl662 marked this pull request as ready for review June 20, 2026 16:32
…r under TS 6.0

API Extractor analyzes each project with its own bundled TypeScript compiler,
which this PR advances to 6.0. TypeScript 6.0 changes the default CommonJS
moduleResolution from "node10" to "bundler", and "bundler" cannot resolve the
types of @modelcontextprotocol/sdk's subpath exports (which lack a "types"
condition) -- producing a TS2307 flood that fails the production build.

Pin moduleResolution to "node10" -- the resolution this project already
compiles under via the repo toolchain -- so API Extractor's analysis matches
the build. No change to the published package.
Comment thread apps/rush-mcp-server/tsconfig.json Outdated
// default CommonJS moduleResolution ("bundler") cannot resolve the types of
// @modelcontextprotocol/sdk's subpath exports (they lack a "types" condition). Pin "node10" --
// the resolution this project already compiles under -- so the analysis matches the build.
"moduleResolution": "node10"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This project compiles using node10 semantics because it's using a 5.x version of TypeScript, right?

Is this something we should inject inside API Extractor so consumers don't need to set this explicitly? If that isn't practical, or comes with unacceptable gotchas, we should at least include docs about this in a migration guide.

@octogonz

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.

This project compiles using node10 semantics because it's using a 5.x version of TypeScript, right?

Right, the build is TS ~5.8 (module: commonjs, no explicit moduleResolution via heft-node-rig), so it gets the node10 default. API Extractor's bundled 6.0 compiler defaults that same config to bundler (TS#62338), which is what surfaced the TS2307s.

Is this something we should inject inside API Extractor so consumers don't need to set this explicitly?

In my opinion, I'm against injecting this inside api extractor. node10 moduleResolution is deprecated in 6.0 and removed in 7.0 (#62200), so API Extractor would be injecting a mode that its bundled compiler will drop next major (it's only green today because the parseJsonConfigFileContent path doesn't surface TS5107). It would also diverge from each downstream consumer's build if some are already on TS 6, and have fixed it themselves.

So instead of pinning node10:

  1. Fixed mcp-server at the source: added .js to the SDK imports; resolves under bundler (and Node at runtime), no deprecated option. Verified under --production. My clanker earlier took the easy way out and assumed just pinning to node10 was the only way to do a simple fix, when this I think is a better solution.
  2. Documented in a new apps/api-extractor/UPGRADING.md what consumers should expect with TS 6, which also covers a supported escape hatch for consumers who must pin resolution: compiler.overrideTsconfig. API Extractor already honors per-project resolution overrides (the bundlerModuleResolution scenario exercises exactly this).

For point 2, I confirmed the overrideTsconfig route works for mcp-server with a quick local test inside apps/rush-mcp-server/config/api-extractor.json:

"compiler": {
  "overrideTsconfig": {
    "extends": "./tsconfig.json",
    "compilerOptions": { "moduleResolution": "node10" }
  }
}

How does this sound? I'm open to a different approach for communicating to consumers, how to migrate, if the new UPGRADE.md isn't what you're looking for.

hl662 added 2 commits June 21, 2026 12:19
…k subpath imports

The SDK's "exports" map ("./*") has no "types" condition and requires extensionful
specifiers. Under TypeScript 6.0's new default `bundler` resolution -- which API
Extractor's bundled 6.0 compiler now uses -- the extensionless subpath imports fail
with TS2307. The extensionless value import in zodTypes also fails at runtime under
Node (MODULE_NOT_FOUND), since Node won't extension-complete an "exports" target either.

Add ".js" to the SDK subpath imports so they resolve under both Node's runtime
resolution and the bundler analysis, and drop the transitional moduleResolution=node10
pin (deprecated in TS 6.0, removed in 7.0).

Also add apps/api-extractor/UPGRADING.md (linked from the README and CHANGELOG)
documenting the bundled-compiler moduleResolution default change for downstream consumers.
Resolve conflicts from upstream:
- apps/playwright-browser-tunnel/package.json: keep upstream's ws ~8.21.0 /
  @types/ws 8.18.1 bump alongside this PR's playwright 1.58.2.
- common/config/subspaces/default/repo-state.json + pnpm-lock.yaml: regenerated
  via `rush update` so the lockfile reflects both changes.

Verified the affected projects (playwright-browser-tunnel, mcp-server,
api-extractor) build clean under `rush rebuild --production`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Needs triage

Development

Successfully merging this pull request may close these issues.

2 participants