Skip to content

@typescript/typescript6 compat package fails to install under Yarn (builtin TypeScript patch hard-errors on missing 'lib/_tsc.js') #4368

Description

@maik-bol

Description:

Summary

The TS6/TS7 side-by-side setup recommended in the TypeScript 7.0 RC announcement fails to install under Yarn (Berry/v4). Aliasing typescript to @typescript/typescript6 triggers Yarn's builtin compat/typescript patch, which hard-errors because the compat package is a thin re-export shim that doesn't ship all of TypeScript's lib/*.js files. A workaround exists (below), but the out-of-the-box experience is a hard failure.

Environment

  • Yarn 4.16.0 (nodeLinker: node-modules)
  • @typescript/typescript6@6.0.1
  • typescript@7.0.1-rc

Setup (the RC blog's recommended npm-alias approach)

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

What happens

yarn install fails during the fetch/patch step:

➤ YN0001: Error: typescript@patch:@typescript/typescript6@npm%3A6.0.1#optional!builtin<compat/typescript>::version=6.0.1&hash=...: ENOENT: no such file or directory, lstat '.../node_modules/typescript/lib/_tsc.js'
    at ... patchPackage ...

Root cause

Two things combine:

  1. Yarn's bundled @yarnpkg/plugin-compat keys its builtin patches purely on the dependency ident. Any dependency whose ident is typescript (regardless of what it resolves to) is rewritten into patch:…#optional!builtin<compat/typescript>. Because the alias keeps the ident typescript, the patch is applied to the compat shim.

  2. The compat package ships only re-export stubs: lib/typescript.js (module.exports = require("typescript")), lib/tsc.js (require("typescript/lib/tsc.js")), and lib/tsserverlibrary.js. It does not ship lib/_tsc.js or lib/_tsserver.js, which the builtin patch's hunks target for modern TS versions (the >=5.7.1-rc patch block, which is what 6.0.1 matches).

The patch's optional! flag is supposed to make this tolerant, but in Yarn's patchPackage only hunk-application errors (the parse/apply error class) are caught and downgraded to a warning. A raw lstat ENOENT on a file the patch intends to modify is rethrown as a hard YN0001, so the optional fallback never engages.

Workaround (confirmed working)

Add the two missing files as re-export stubs via a Yarn patch on the compat package, then reference it through the alias so the stub patch applies before Yarn's builtin patch. With the files present, the builtin patch's lstat succeeds, its hunks then fail and are correctly swallowed by optional! (downgraded to YN0066: Cannot apply hunk #1, a warning), and install completes.

Stub patch contents:

diff --git a/lib/_tsc.js b/lib/_tsc.js
new file mode 100644
--- /dev/null
+++ b/lib/_tsc.js
@@ -0,0 +1 @@
+require("typescript/lib/_tsc.js");
diff --git a/lib/_tsserver.js b/lib/_tsserver.js
new file mode 100644
--- /dev/null
+++ b/lib/_tsserver.js
@@ -0,0 +1 @@
+require("typescript/lib/_tsserver.js");

Declared so the stub applies first and Yarn wraps the builtin patch around it:

{
  "devDependencies": {
    "typescript": "patch:@typescript/typescript6@npm%3A6.0.1#~/.yarn/patches/@typescript-typescript6-npm-6.0.1.patch",
    "typescript-7": "npm:typescript@rc"
  }
}

Result: tsc → 7.0.1-rc, tsc6 → 6.0.x, and bare import "typescript" → the TS6 API, all working.

Why this matters

The npm-alias approach is exactly what the RC announcement recommends, and tools like typescript-eslint and @0no-co/graphqlsp import the bare typescript specifier, so keeping the typescript ident via the alias is effectively required. Under Yarn this is a hard install failure unless users discover the patch-the-shim workaround.

Suggested fix

Have @typescript/typescript6 ship re-export stubs for the full set of files Yarn's builtin patch targets (at minimum lib/_tsc.js and lib/_tsserver.js; ideally also lib/tsserver.js, lib/typingsInstaller.js, lib/typescriptServices.js for forward-compatibility). Then the builtin patch's lstat succeeds and the hunks fail-and-skip gracefully, with no user-side workaround needed.

Alternatively (or additionally): document an official Yarn setup, and/or coordinate with the Yarn team so the builtin compat/typescript patch treats missing target files as a tolerated/optional case rather than a hard error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions