Skip to content

Conversation

@PaulyBearCoding
Copy link

Fixes #62706

Problem

Import path completions were missing for package.json exports using wildcard patterns with file extensions.

Example:

{
  "exports": {
    "./glob/path/*.js": "./build/*.js"
  }
}

Typing import {} from "@local/a/glob/path/" should suggest bar.js, baz.js but completions were missing.

Root Cause

Two bugs in src/services/stringCompletions.ts:

  1. Line 1234: Wildcard detection used endsWith(pattern, "/*") which only matched patterns ending with "/*", missing patterns like "./path/*.js"

  2. Line 1166-1168: Completion generation didn't append file extension suffixes from patterns

Solution

Change 1: Broaden wildcard detection (Line 1234)

// Before
const isExportsOrImportsWildcard = (isExports || isImports) && endsWith(pattern, "/*");

// After
const isExportsOrImportsWildcard = (isExports || isImports) && pattern.includes("/*");

This correctly detects all Node.js wildcard patterns containing "/*" regardless of trailing characters.

Change 2: Append file extension suffixes (Line 1166-1168)

// Before
return flatMap(patterns, pattern => getModulesForPathsPattern(...));

// After
return flatMap(patterns, pattern =>
    getModulesForPathsPattern(...)
        ?.map(entry => parsedPath.suffix && startsWith(parsedPath.suffix, ".")
            ? { ...entry, name: entry.name + parsedPath.suffix }
            : entry)
);

This adds file extension suffixes (.js, .css, .d.ts, etc.) to completions while correctly ignoring path components (like "/suffix").

Testing

New Test Case

Added tests/cases/fourslash/completionForPackageExportsGlobWithExtension.ts to verify wildcard patterns with extensions work correctly.

Validation Results

Before fix:

  • 99,000 passing
  • 1 failing (new test: "Error: completion 'bar.js' not found")

After fix:

  • 99,001 passing
  • 0 failing
  • 0 regressions

Patterns Fixed

  • "./glob/path/*.js"
  • "./styles/*.css"
  • "./dist/*.d.ts"
  • "./esm/*.mjs"
  • "./cjs/*.cjs"
  • And more...

Compliance

Aligns with Node.js Package Entry Points specification which supports wildcard patterns like:

{
  "exports": {
    "./features/*.js": "./src/features/*.js",
    "./lib/*/index.js": "./src/*/index.js"
  }
}

All valid patterns contain "/*" substring.

Files Changed

  • src/services/stringCompletions.ts (2 lines modified)
  • tests/cases/fourslash/completionForPackageExportsGlobWithExtension.ts (new test)

…meters

Fixes microsoft#62693

## Problem

When a generic function has overloads with mixed parameter types (function vs object literal), TypeScript shows incorrect completions for object literals. For example:

```typescript
declare function task<T>(make: () => T): void
declare function task<T>(arg: {make: () => T}): void

task({
    // BUG: Shows bind, call, apply instead of "make"
})
```

The editor shows function properties (bind, call, apply) instead of the expected object property "make".

## Root Cause

During completion, generic type inference is blocked (type parameters are unknown). When `chooseOverload` evaluates candidates, it:

1. Attempts to resolve the function-type overload first
2. Cannot infer `T` during completion context
3. Falls back to treating the object literal as a function type
4. Returns function properties instead of object properties

The issue occurs because overload selection doesn't account for the syntactic context (completing an object literal) when generic inference is unavailable.

## Solution

The fix tracks which argument position is being completed and uses this information during overload resolution to prefer object-type overloads when completing object literals.

### Changes

**types.ts (line 6311):**
Added `completionArgumentIndex` to NodeLinks to track which argument is being completed.

**checker.ts (lines 32072-32076):**
Store the argument index when inference is blocked during completion:
```typescript
if (isInferencePartiallyBlocked) {
    links.completionArgumentIndex = argIndex;
}
```

**checker.ts (lines 36728-36832):**
Enhanced `chooseOverload` to:
1. Detect when completing an object literal at argument position 0
2. Skip overload candidates with function-type parameters
3. Accept object-type overload candidates even if the literal is incomplete

This allows the type checker to select the correct overload based on syntactic context rather than relying solely on type inference.

## Why This Works

The fix is surgical and only affects generic overload resolution during completion:

- **Targeted scope:** Only triggers for object literals at argument 0 with blocked inference
- **Preserved behavior:** Non-generic overloads and other arguments remain unchanged
- **Syntactic guidance:** Uses the object literal syntax to disambiguate overloads when type inference is unavailable

The approach respects TypeScript's existing completion infrastructure while providing better overload selection for this specific edge case.

## Testing

Added comprehensive test coverage in `completionForGenericOverloadObjectLiteral.ts`:
- Generic function-first overload (the bug)
- Generic object-first overload (control)
- Non-generic overload (control)
- Multiple type parameters with optional properties (rigorous)

All tests verify that object properties appear in completions and function properties (bind, call, apply) are correctly excluded.

Test results: 99,000 passing, 0 regressions
Fixes microsoft#62706

Import path completions were missing for package.json exports using
wildcard patterns with file extensions (e.g., "./glob/path/*.js").

Two issues in stringCompletions.ts:

1. Wildcard detection used endsWith(pattern, "/*") which only matched
   patterns ending with "/*", missing patterns like "./path/*.js".
   Changed to pattern.includes("/*") to detect all valid patterns.

2. Completion generation didn't append file extension suffixes from
   patterns. Added logic to append suffixes that are file extensions
   (start with ".") while correctly ignoring path components.

Test results: 99,001 passing, 0 regressions
@github-project-automation github-project-automation bot moved this to Not started in PR Backlog Nov 15, 2025
@typescript-bot typescript-bot added the For Backlog Bug PRs that fix a backlog bug label Nov 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Backlog Bug PRs that fix a backlog bug

Projects

Status: Not started

Development

Successfully merging this pull request may close these issues.

Import path completions don't include file extensions that are part of export wildcard globs

2 participants