Skip to content

Fix auto-import of subpath imports starting with #/ in supported module resolution modes#3123

Merged
andrewbranch merged 5 commits intomicrosoft:mainfrom
andrewbranch:copilot/absent-bedbug
Mar 24, 2026
Merged

Fix auto-import of subpath imports starting with #/ in supported module resolution modes#3123
andrewbranch merged 5 commits intomicrosoft:mainfrom
andrewbranch:copilot/absent-bedbug

Conversation

@andrewbranch
Copy link
Copy Markdown
Member

@andrewbranch andrewbranch commented Mar 17, 2026

Auto-imports was never updated to allow subpath imports starting with #/ after microsoft/TypeScript#62844 landed. Same as with module resolution, they're only considered valid in --moduleResolution nodenext and bundler.

Fixes #2984

Copilot AI review requested due to automatic review settings March 17, 2026 16:17
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR investigates #2984 (auto-import preferring deep relative paths over shorter package.json#imports root wildcard aliases) and applies a minimal fix so #/* mappings can contribute #/... module specifiers during auto-import generation.

Changes:

  • Add investigation notes documenting repro, root cause, and fix.
  • Update tryGetModuleNameFromPackageJsonImports to allow the #/* root wildcard imports key.
  • Add a focused fourslash test covering the #/* -> #/... auto-import preference for both shortest and non-relative.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
investigations/issue-2984-autoimport-root-wildcard.md Documents repro, diagnosis, and validation for #2984.
internal/modulespecifiers/specifiers.go Adjusts imports-key validation to permit #/* root wildcard.
internal/fourslash/tests/autoImport_issue2984_rootWildcardVitest_test.go Adds regression test asserting #/... is top-ranked over deep relative specifiers.

You can also share your feedback on Copilot code review. Take the survey.

andrewbranch and others added 3 commits March 17, 2026 09:24
… not just #/*

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Restructure validation logic for clarity
- Rewrite fourslash tests using BaselineAutoImports
- Delete investigation notes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@andrewbranch andrewbranch changed the title Investigate #2984: root wildcard package imports in auto-import Fix auto-import of subpath imports starting with #/ in supported module resolution modes Mar 17, 2026
```ts
// @FileName: /src/features/deep/consumer.ts
entit/**/
``````ts
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 seems broken, and the next like is missing a file path - what's going on here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

These baselines have always been missing a newline. I'll fix them all in a separate PR but the baseline still shows everything is working.

entries := top.Entries()
for k, value := range entries {
if !strings.HasPrefix(k, "#") || k == "#" || strings.HasPrefix(k, "#/") {
if k == "#" || k == "#/" || !strings.HasPrefix(k, "#") {
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 is surprising - does the blog post need to be updated?

Image

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, --moduleResolution node20 doesn't exist yet. Everything else is right.

Copy link
Copy Markdown
Member

@DanielRosenwasser DanielRosenwasser Mar 17, 2026

Choose a reason for hiding this comment

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

But this logic says that "#" and "#/" are invalid entries in "imports" - so am I misunderstanding?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

They are, aren't they? You need something after that prefix.

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.

Sorry, to be explicit - the blog post example uses a bare # entry, which is not being used as a prefix.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Omg, sorry, I totally missed that. I was only focused on the highlighted text. Yes, the blog post needs to be updated:

Developer/eg/imports                                                                              v24.14.0
❯ node index.js
node:internal/modules/esm/resolve:698
    throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, fileURLToPath(base));
          ^

TypeError [ERR_INVALID_MODULE_SPECIFIER]: Invalid module "#" is not a valid internal imports specifier name imported from /Users/andrew/Developer/eg/imports/index.js
    at packageImportsResolve (node:internal/modules/esm/resolve:698:11)
    at moduleResolve (node:internal/modules/esm/resolve:848:16)
    at defaultResolve (node:internal/modules/esm/resolve:991:11)
    at #cachedDefaultResolve (node:internal/modules/esm/loader:719:20)
    at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:736:38)
    at ModuleLoader.resolveSync (node:internal/modules/esm/loader:765:52)
    at #resolve (node:internal/modules/esm/loader:701:17)
    at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:621:35)
    at ModuleJob.syncLink (node:internal/modules/esm/module_job:160:33)
    at ModuleJob.link (node:internal/modules/esm/module_job:245:17) {
  code: 'ERR_INVALID_MODULE_SPECIFIER'
}

Node.js v24.14.0

Developer/eg/imports                                                                              v24.14.0
❯ node index.js
node:internal/modules/esm/resolve:698
    throw new ERR_INVALID_MODULE_SPECIFIER(name, reason, fileURLToPath(base));
          ^

TypeError [ERR_INVALID_MODULE_SPECIFIER]: Invalid module "#/" is not a valid internal imports specifier name imported from /Users/andrew/Developer/eg/imports/index.js
    at packageImportsResolve (node:internal/modules/esm/resolve:698:11)
    at moduleResolve (node:internal/modules/esm/resolve:848:16)
    at defaultResolve (node:internal/modules/esm/resolve:991:11)
    at #cachedDefaultResolve (node:internal/modules/esm/loader:719:20)
    at #resolveAndMaybeBlockOnLoaderThread (node:internal/modules/esm/loader:736:38)
    at ModuleLoader.resolveSync (node:internal/modules/esm/loader:765:52)
    at #resolve (node:internal/modules/esm/loader:701:17)
    at ModuleLoader.getOrCreateModuleJob (node:internal/modules/esm/loader:621:35)
    at ModuleJob.syncLink (node:internal/modules/esm/module_job:160:33)
    at ModuleJob.link (node:internal/modules/esm/module_job:245:17) {
  code: 'ERR_INVALID_MODULE_SPECIFIER'
}

Node.js v24.14.0

@andrewbranch andrewbranch added this pull request to the merge queue Mar 24, 2026
Merged via the queue into microsoft:main with commit 51d05e9 Mar 24, 2026
21 checks passed
@andrewbranch andrewbranch deleted the copilot/absent-bedbug branch March 24, 2026 21:26
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.

Auto-import with subpath imports always prioritizes relative imports

4 participants