Skip to content

Handle optional compat patch failures for TypeScript 7 - #7190

Merged
arcanis merged 3 commits into
yarnpkg:masterfrom
hamidrezahanafi:fix-typescript-7-compat-patch
Jul 1, 2026
Merged

Handle optional compat patch failures for TypeScript 7#7190
arcanis merged 3 commits into
yarnpkg:masterfrom
hamidrezahanafi:fix-typescript-7-compat-patch

Conversation

@hamidrezahanafi

@hamidrezahanafi hamidrezahanafi commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Bound the generated TypeScript compatibility patch to TypeScript versions before 7.0.0, and committed the matching generated patch artifact so the compat patch generator stays reproducible.
  • Fixed optional patch handling so optional! patches fall back when a package no longer ships a target file (for example lib/_tsc.js in TypeScript 7 / TypeScript compatibility shims), instead of failing the install with ENOENT.
  • Added regression coverage for both direct typescript@7.0.1-rc installs and the TypeScript 7 side-by-side recommendation where the typescript ident aliases to npm:@typescript/typescript6@^6.0.0.
  • Stabilized the scoped plugin-typescript acceptance test by moving it from @babel/traverse (now reported by npm search metadata as having included types) to a fixture package that still exercises DefinitelyTyped scoped package insertion.
  • Added deferred version metadata for the changed workspaces.

Test plan

  • yarn workspace @yarnpkg/plugin-compat test:plugin-compat
  • yarn test:unit packages/plugin-patch
  • node ./scripts/run-yarn.js test:integration packages/acceptance-tests/pkg-tests-specs/sources/plugins/plugin-typescript.test.ts
  • yarn version check

Notes

TypeScript 7 ships a native compiler package layout and no longer has the legacy JS compiler files patched by the existing PnP compatibility diff, such as lib/_tsc.js. Bounding the TypeScript compat patch makes this intent explicit, while the optional patch fallback fixes the broader bug that optional! patch failures caused by missing target files were still fatal.

TypeScript 7 support should ship with microsoft/typescript-go#1966.

Made with Cursor

@maik-bol

Copy link
Copy Markdown

Thanks for this. Bounding the patch to < 7.0.0 fixes the plain typescript@7.x install, but I think it leaves a closely related case still broken, and it might be worth addressing the root cause while we're here.

The TypeScript 7.0 RC announcement recommends a side-by-side install that aliases typescript to the TS6 compatibility package:

{
  "devDependencies": {
    "typescript": "npm:@typescript/typescript6@^6.0.0",
    "typescript-7": "npm:typescript@rc"
  }
}

@typescript/typescript6 is a thin re-export shim (version 6.0.1) that does not ship lib/_tsc.js / lib/_tsserver.js. Because the compat plugin keys on the dependency ident (typescript) before resolution, Yarn applies the builtin patch to this shim. Its version is 6.0.1, so a < 7 gate still selects it, and the install dies with the same YN0001 ENOENT on lib/_tsc.js. So this PR fixes installing TS7 directly, but not the recommended TS6/TS7 coexistence setup.

Repro on node-modules (no PnP):

# .yarnrc.yml
nodeLinker: node-modules
{ "devDependencies": { "typescript": "npm:@typescript/typescript6@^6.0.0" } }

yarn install -> YN0001: ... ENOENT ... lstat '.../typescript/lib/_tsc.js'.

Two more robust options, either of which also covers the alias case:

  1. Gate on resolved package identity, not (only) version. Apply the patch only when the typescript-ident descriptor actually resolves to the typescript package, and skip it when it resolves to something else via an npm: alias. That fixes both the TS7 case and the compat-alias case without relying on a version cutoff.
  2. Make optional! tolerate a missing target file. Today the apply step only swallows hunk-application failures; a raw lstat ENOENT on a file the package doesn't ship is rethrown as a hard YN0001, even though the descriptor is marked optional!. Treating a missing target file like a failed hunk (warn and fall back to the original source) would make this and any future layout drift non-fatal.

(1) is the precise fix; (2) is good defense-in-depth and matches what the docs say optional! already does.

Happy to help if you want it!

@arcanis

arcanis commented Jun 18, 2026

Copy link
Copy Markdown
Member

I think the optional qualifier being ignored is a proper bug to fix, yeah - also something curious in the current PR, it seems to be breaking a test 🤔

@hamidrezahanafi

Copy link
Copy Markdown
Contributor Author

Thanks @maik-bol and @arcanis , that makes sense.

I updated the PR to address this in two layers:

  • Kept the explicit TypeScript compat patch bound to <7.0.0-0, so it’s clear that the legacy PnP patch is only intended for the old JS-based TypeScript package layout.
  • Fixed the broader optional! behavior in plugin-patch: if an optional patch targets a file that the package no longer ships, Yarn now treats that like an optional patch miss, warns, discards the patch attempt, and falls back to the original package instead of failing with ENOENT.

I also added coverage for the alias case from the TS 7 recommendation:

{
  "typescript": "npm:@typescript/typescript6@^6.0.0"
}

So this should cover both direct typescript@7.x installs and the TS6/TS7 side-by-side setup.

On the CI failure: plugin-typescript.test.ts was failing because the test used @babel/traverse as a scoped package that should get @types/babel__traverse auto-added. That depends on live npm-search / Algolia metadata. That metadata now reports @babel/traverse as having included types, so Yarn correctly skipped adding the @types package and the assertion failed. I changed the test to use a fixture package whose metadata still exercises the DefinitelyTyped scoped-package path, so the test remains focused on Yarn’s scoped @types/foo__bar behavior instead of depending on stale metadata for @babel/traverse.

@hamidrezahanafi hamidrezahanafi changed the title Limit TypeScript compat patch to pre-7 releases Handle optional compat patch failures for TypeScript 7 Jun 19, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
@hamidrezahanafi
hamidrezahanafi force-pushed the fix-typescript-7-compat-patch branch from 1c09061 to ce3dafd Compare June 19, 2026 04:29
@hamidrezahanafi
hamidrezahanafi requested a review from arcanis as a code owner June 19, 2026 04:29
Co-authored-by: Cursor <cursoragent@cursor.com>
@maik-bol

Copy link
Copy Markdown

Thanks @maik-bol and @arcanis , that makes sense.

I updated the PR to address this in two layers:

  • Kept the explicit TypeScript compat patch bound to <7.0.0-0, so it’s clear that the legacy PnP patch is only intended for the old JS-based TypeScript package layout.
  • Fixed the broader optional! behavior in plugin-patch: if an optional patch targets a file that the package no longer ships, Yarn now treats that like an optional patch miss, warns, discards the patch attempt, and falls back to the original package instead of failing with ENOENT.

I also added coverage for the alias case from the TS 7 recommendation:

{
  "typescript": "npm:@typescript/typescript6@^6.0.0"
}

So this should cover both direct typescript@7.x installs and the TS6/TS7 side-by-side setup.

On the CI failure: plugin-typescript.test.ts was failing because the test used @babel/traverse as a scoped package that should get @types/babel__traverse auto-added. That depends on live npm-search / Algolia metadata. That metadata now reports @babel/traverse as having included types, so Yarn correctly skipped adding the @types package and the assertion failed. I changed the test to use a fixture package whose metadata still exercises the DefinitelyTyped scoped-package path, so the test remains focused on Yarn’s scoped @types/foo__bar behavior instead of depending on stale metadata for @babel/traverse.

Amazing work, thanks for the effort!

@ryami333

ryami333 commented Jun 29, 2026

Copy link
Copy Markdown

Really hope this gets merged sooner rather than later – would be absurd if Typescript 7.0 drops this week and Yarn users can't use it, not because it can't be fixed, but because it just hasn't been prioritised.

our current plan is to release TypeScript 7.0 within the next month

– The TypeScript Team, June 18th

@hamidrezahanafi

Copy link
Copy Markdown
Contributor Author

@arcanis would you please take a look? any issues with the PR?

@arcanis
arcanis merged commit fe04180 into yarnpkg:master Jul 1, 2026
27 of 29 checks passed
@MarcAurel

Copy link
Copy Markdown

@arcanis any plan to release this?

@arcanis

arcanis commented Jul 8, 2026

Copy link
Copy Markdown
Member

Just released in 4.17.1, thanks for your patience 🙏

@robrichard

Copy link
Copy Markdown

Seems like there is still an issue with the recommended side by side install. node_modules/.bin/tsc gets linked to the transitive dependency on typescript 6, and not the direct dependency on typescript v7. I opened an issue here: #7215

ReDrUm pushed a commit to ReDrUm/yarn-berry that referenced this pull request Jul 10, 2026
## Summary

- Bound the generated TypeScript compatibility patch to TypeScript
versions before 7.0.0, and committed the matching generated patch
artifact so the compat patch generator stays reproducible.
- Fixed optional patch handling so `optional!` patches fall back when a
package no longer ships a target file (for example `lib/_tsc.js` in
TypeScript 7 / TypeScript compatibility shims), instead of failing the
install with `ENOENT`.
- Added regression coverage for both direct `typescript@7.0.1-rc`
installs and the TypeScript 7 side-by-side recommendation where the
`typescript` ident aliases to `npm:@typescript/typescript6@^6.0.0`.
- Stabilized the scoped `plugin-typescript` acceptance test by moving it
from `@babel/traverse` (now reported by npm search metadata as having
included types) to a fixture package that still exercises
DefinitelyTyped scoped package insertion.
- Added deferred version metadata for the changed workspaces.

## Test plan

- `yarn workspace @yarnpkg/plugin-compat test:plugin-compat`
- `yarn test:unit packages/plugin-patch`
- `node ./scripts/run-yarn.js test:integration
packages/acceptance-tests/pkg-tests-specs/sources/plugins/plugin-typescript.test.ts`
- `yarn version check`

## Notes

TypeScript 7 ships a native compiler package layout and no longer has
the legacy JS compiler files patched by the existing PnP compatibility
diff, such as `lib/_tsc.js`. Bounding the TypeScript compat patch makes
this intent explicit, while the optional patch fallback fixes the
broader bug that `optional!` patch failures caused by missing target
files were still fatal.

TypeScript 7 support should ship with microsoft/typescript-go#1966.

Made with Cursor

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: John Doe <you@example.com>
Co-authored-by: Maël Nison <mael.nison@mistral.ai>
jxn-30 added a commit to jxn-30/better-moodle that referenced this pull request Jul 12, 2026
the upgrade to yarn 4.17.1 is necessary as a bug with installing typescript v7 has been fixed: yarnpkg/berry#7190
the double-installation is necessary, as typescript v7 does not have an API yet, thus typescript-eslint otherwise could not use it: typescript-eslint/typescript-eslint#10940 & https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/#running-side-by-side-with-typescript-6.0
helperbot-recidiviz pushed a commit to Recidiviz/pulse-dashboards that referenced this pull request Jul 30, 2026
## Description of the change

TypeScript 7 is [officially out
today](https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/)
and this PR gets us on board with its super-speedy goodness. TS7
introduces a new `tsc` implementation written in go, which on my machine
reduces `nx typecheck staff`'s runtime from over a minute to 15-20
seconds.

Here are the changes that were required:
* This PR is stacked on
Recidiviz/recidiviz-dashboards#14630 to get us
nx 22, which fixed a path resolution bug: ts7 removed baseUrl as a
tsconfig option in favor of anchoring all path aliases directly.
* Upgraded yarn to let it install ts7 cleanly
(yarnpkg/berry#7190)
* Exempted typescript 7.0.2 from the yarn age gate because this is a
known, high-profile release with big upside
* Replaced nxViteTsPaths() with vite-tsconfig-paths: the former is
deprecated in nx 22 and shares the aforementioned baseUrl issue. The new
package also doesn't need the big list of asset extensions we had to add
in the nx 22 upgrade pr.
* Changed moduleResolution from node to bundler: ts7 doesn't support the
former, and the latter better matches what we're actually doing at
runtime anyway.
* Stopped emitting declarations from some libraries. Ts7 was erroring on
these, but we're not actually using them anywhere
* Fixed/tightened up various minor latent typing issues
* By default, tsc launches four parallel typecheckers in each process. I
found that when checking staff this ate up all my memory and started
choking on swap. Reducing it to two (just for that project) seemed to
give the best results. I've got an M2 Pro with 16GB of RAM. I'd be
interested to see others' results here.

## Type of change

> All pull requests must have at least one of the following labels
applied (otherwise the PR will fail):

| Label | Description |
| --------------------------- |
---------------------------------------------------------------------------------------------------------
|
| Type: Bug | non-breaking change that fixes an issue |
| Type: Feature | non-breaking change that adds functionality |
| Type: Breaking Change | fix or feature that would cause existing
functionality to not work as expected |
| Type: Non-breaking refactor | change addresses some tech debt item or
prepares for a later change, but does not change functionality |
| Type: Configuration Change | adjusts configuration to achieve some end
related to functionality, development, performance, or security |
| Type: Dependency Upgrade | upgrades a project dependency - these
changes are not included in release notes |

## Related issues

Closes #XXXX

Resolve Sentry issue:
Fixes RECIDIVIZ-PULSE-DASHBOARD-[XXX]

## Checklists

### Development

These boxes should be checked by the submitter prior to merging:

- [ ] Manual testing against realistic data has been performed locally
- [ ] E2E have been run for Lantern changes ([Steps in the
Readme](https://github.com/Recidiviz/recidiviz-dashboards#running-e2e-tests))

### Code review

These boxes should be checked by reviewers prior to merging:

- [x] This pull request has a descriptive title and information useful
to a reviewer
- [x] Potential security implications or infrastructural changes have
been considered, if relevant

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GitOrigin-RevId: 856d93ab41f0414ac72bcf5a7e182e6792af5cf0
shakuzen added a commit to JapanFinance/wiki that referenced this pull request Aug 2, 2026
Dependabot's daily typescript bump attempt (6.0.3 -> 7.0.2) was
failing with:

  YN0001: typescript@patch:...builtin<compat/typescript>: ENOENT:
  no such file or directory, lstat '/node_modules/typescript/lib/_tsc.js'

Yarn's builtin compat/typescript patch assumes the legacy JS
compiler file layout, which TypeScript 7's native compiler package
no longer has. This was fixed upstream in yarnpkg/berry#7190
(released in Yarn 4.17.1) by bounding the patch to TypeScript <7
and making optional patch failures non-fatal. 4.18.0 additionally
picks up #7216, a related bin-precedence fix for the recommended
TS 6/7 side-by-side setup.

Verified by reproducing Dependabot's exact command
(`yarn install --mode=update-lockfile` with typescript bumped to
7.0.2) against the new Yarn version, which now succeeds.

Also keeps enableScripts on Yarn's actual default (false, since
4.14) rather than the blanket `true` its version-migration step
would otherwise have pinned, and allowlists only the three packages
that ship native binaries this project's tooling actually needs
(esbuild, @swc/core, workerd) via dependenciesMeta.built. core-js's
postinstall is a no-op sponsorship banner and doesn't need it.
approvedGitRepositories is left empty since this repo has no git
dependencies.
shakuzen added a commit to JapanFinance/wiki that referenced this pull request Aug 2, 2026
Dependabot's daily typescript bump attempt (6.0.3 -> 7.0.2) was
failing with:

  YN0001: typescript@patch:...builtin<compat/typescript>: ENOENT:
  no such file or directory, lstat '/node_modules/typescript/lib/_tsc.js'

Yarn's builtin compat/typescript patch assumes the legacy JS
compiler file layout, which TypeScript 7's native compiler package
no longer has. This was fixed upstream in yarnpkg/berry#7190
(released in Yarn 4.17.1) by bounding the patch to TypeScript <7
and making optional patch failures non-fatal. 4.18.0 additionally
picks up #7216, a related bin-precedence fix for the recommended
TS 6/7 side-by-side setup.

Verified by reproducing Dependabot's exact command
(`yarn install --mode=update-lockfile` with typescript bumped to
7.0.2) against the new Yarn version, which now succeeds.

Also keeps enableScripts on Yarn's actual default (false, since
4.14) rather than the blanket `true` its version-migration step
would otherwise have pinned, and allowlists only the three packages
that ship native binaries this project's tooling actually needs
(esbuild, @swc/core, workerd) via dependenciesMeta.built. core-js's
postinstall is a no-op sponsorship banner and doesn't need it.
approvedGitRepositories is left empty since this repo has no git
dependencies.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants