Skip to content

createDefaultMapFromNodeModules can't find lib.*.d.ts under the official @typescript/typescript6 (TS 7 side-by-side) wrapper #3645

Description

@andrepav1

Summary

createDefaultMapFromNodeModules locates the bundled lib.*.d.ts with path.dirname(require.resolve("typescript")). When typescript resolves to a re-export wrapper instead of a normal install, that path is the wrapper's own lib/ directory, which does not contain the stdlib .d.ts files. The returned map is built without them, and the VFS later throws when the program asks for one.

This reproduces with the official TypeScript 7.0 side-by-side package, @typescript/typescript6.

Environment

  • @typescript/vfs 1.6.1 (the same code is in 1.6.4)
  • typescript aliased to @typescript/typescript6@6.0.2, per the TS 7.0 release notes, Running side-by-side with TypeScript 6.0: npm install -D typescript@npm:@typescript/typescript6

Repro

  1. npm i -D typescript@npm:@typescript/typescript6
  2. createDefaultMapFromNodeModules(compilerOptions) and build a program from the map.

Result:

TSVFS: A request was made for .../@typescript/typescript6/lib/lib.es2020.d.ts
but there wasn't a file found in the file map.

Root cause

@typescript/typescript6 is a thin re-export. Its entry file is:

// @typescript/typescript6/lib/typescript.js
module.exports = require('@typescript/old'); // = the real typescript@6.x, which ships the lib.*.d.ts

So the actual lib.*.d.ts live in the nested @typescript/old/lib/, not in @typescript/typescript6/lib/.

require.resolve("typescript") returns the wrapper's entry file (.../@typescript/typescript6/lib/typescript.js); it does not follow the runtime re-export. So in createDefaultMapFromNodeModules:

const lib = tsLibDirectory || path.dirname(require.resolve('typescript'));
// ...
const libFiles = fs.readdirSync(tsLibDirectory || path.dirname(require.resolve('typescript')));

lib points at the wrapper's lib/, which has typescript.js / tsc.js but none of the lib.*.d.ts. libFiles is therefore effectively empty and the default map is missing the stdlib.

Expected

The default map should include the stdlib lib.*.d.ts when typescript resolves through a re-export/alias, the same as for a plain install.

Suggested fix

Derive the lib directory from the compiler's getDefaultLibFilePath, which uses the executing file path and so follows the re-export to @typescript/old, instead of require.resolve:

const ts = _ts ?? require('typescript');
const libDir = tsLibDirectory ?? path.dirname(ts.getDefaultLibFilePath(compilerOptions));

This preserves the existing tsLibDirectory override, needs no change from callers (e.g. @ark/attest calls createDefaultMapFromNodeModules(compilerOptions) with no tsLibDirectory), and works for both plain and aliased/wrapped installs. Happy to open a PR.

Related

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions