Skip to content

fix: fall back to bundled TypeScript when typescript is not installed - #1346

Open
SammyTourani wants to merge 1 commit into
vercel:mainfrom
SammyTourani:fix/issue-1264
Open

SammyTourani wants to merge 1 commit into
vercel:mainfrom
SammyTourani:fix/issue-1264

Conversation

@SammyTourani

Copy link
Copy Markdown

Fixes #1264

  • src/typescript.js: when there's no project-local typescript, fall back to require('./loaders/ts-loader.js').typescript. This is the same fallback dist/ncc/typescript.js had up to 0.24.1.
    • In dist/, this is the compiler bundled into loaders/ts-loader.js. Webpack has already loaded that module as the loader, so it isn't evaluated a second time.
    • From src/ (coverage runs), src/loaders/ts-loader.js re-exports the typescript devDependency, so behaviour there doesn't change.
  • scripts/build.js: copy TypeScript's lib .d.ts files to dist/ncc/loaders/ instead of dist/ncc/loaders/typescript/lib/.
    • Since TypeScript 5.0, getDefaultLibFilePath() looks for them next to sys.getExecutingFilePath(), which for the bundled compiler is dist/ncc/loaders/ts-loader.js.
    • Without this, type-checking with the built-in compiler fails with TS6053: File '.../dist/ncc/loaders/lib.es6.d.ts' not found.
    • The files and the package size stay the same; only the directory changes.
  • test/cli.test.js: a new test copies dist/ncc to a temp directory outside the repo, so typescript can't be resolved from ncc's location (as with a global install).
    • It builds test/integration/test.ts with TYPESCRIPT_LOOKUP_PATH pointing nowhere and expects the build to succeed with the built-in compiler.
    • The existing "ncc built-in" test can't catch this bug, because inside the repo require('typescript') finds the repo's own node_modules/typescript.
    • The new test is skipped under coverage, which runs from src/, where there is no bundle.

A project's own typescript is still used first. This only changes what happens when there isn't one.

Verification

Environment: macOS, Node 26.3.1. Setup: pnpm install --frozen-lockfile, pnpm build-test-binary, pnpm build.

Command: node --expose-gc --max_old_space_size=4096 node_modules/jest/bin/jest.js test/cli.test.js -t "built-in typescript when typescript is not installed"
Result:

  • On main, the test fails with the issue's error (Could not load TypeScript compiler with NPM package name .../typescript.js).
  • With only the src/typescript.js change, it fails with TS6053: File '.../loaders/lib.es6.d.ts' not found.
  • With both changes, it passes (Tests: 23 skipped, 1 passed, 24 total).

Command: pnpm test
Result:

  • This branch: Test Suites: 4 passed, 4 total, Tests: 122 passed, 122 total.
  • main plus only the new test: Tests: 1 failed, 121 passed, 122 total. The only failure is the new test.
  • An earlier full run on this branch reported Tests: 1 failed, 121 passed, 122 total. The failure was test/watcher.test.js › Should support custom watch API exceeding its 30 s timeout. That test watch-builds twilio, with no TypeScript involved. It passed when run alone (24.8 s) and in the run above. On main it took 23.7 s of its 30 s budget.

Command: node --expose-gc --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --coverage --globals '{"coverage":true}' test/cli.test.js (runs the CLI tests from src/)
Result: Tests: 23 passed, 23 total

Manual check of the reported scenario: I packed the build with npm pack and installed it with npm install -g --prefix <tmp>, in a directory tree with no typescript package anywhere.

  • In a "type": "module" project (the issue's case), ncc run src/index.ts prints ncc: Using typescript@5.9.3 (ncc built-in) and runs the program. The published 0.45.0 fails in the same setup with the issue's error.
  • Type errors are still reported (TS2322, exit code 1). -t still works, and --quiet still prints nothing.
  • A project with its own typescript@5.4.5 still uses it (ncc: Using typescript@5.4.5 (local user-provided)).

Since 0.25.0 the published dist/ncc/typescript.js falls back to a bare
require('typescript'), which fails when no typescript package can be
resolved from ncc's install location (e.g. a global install), even though
loaders/ts-loader.js bundles a TypeScript compiler. Fall back to that
bundled compiler again, and copy its default lib .d.ts files to
dist/ncc/loaders/, where TypeScript 5 looks for them.

Fixes vercel#1264
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.

Error: Could not load TypeScript compiler with NPM package name

1 participant