microsoft / microsoft/TypeScript

Method overloads fail to resolve correctly when using mapped types with conditional generics and optional parameters

Offen
#62,377 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Needs More Info
Vorherrschende Sprache
Go
Sterne
111k
Forks
14.3k
Ø Merge
2 T. 4 Std.
Gemergte PRs (30 T.)
132

Beschreibung

### 🔎 Search Terms

method overload, generic mapped types, conditional generics, overload resolution, optional parameters, Parameters utility type, ReturnType, ConfigurableAPI, overload lost mapped type, call method generic, generic constraint overload

### 🕗 Version & Regression Information

- This is the behavior in every version I tried, and I reviewed the FAQ for entries about overloads and generics
- I was unable to test this on prior versions because the behavior has been consistent since at least 4.9.5

### ⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.9.2#code/PTAEFkEsDtIWwIYBtQCcCmAHVB7AJgK4DGALpDtKAM4AWOA7jAOagk3qgBGBTAsAFBEkCKlVABBAAoBJADwAVUOgAeJdNDxiASuiI5UeWVRKpmAGlAAKAHS2EqJlQBcoBNACeAbQC6ASlAAvAB8rh5BIQDeAqCgetDGqMQk+pbYkABuCGqgcOhs+M6g8v4RAL7RoBUgEHl0eKA46eioSDgImqAAZvpceWqooAAiABoVRMhIsgDSSqrqHQDW6O44nUVBlrn5eC5Tvi46JASo0PLumOgKnlPeQQDcYxPTs2oaYksra-IbW3W7FrZrPZHC5JPYEFtmlQrjcgvtQIdjqdzpd5Ndbg9+DFxkhJjMVK9FstVutNrV8P9QIDgYU3F4-Ac8kizhcYbdQFEsTE0EyTqwaJAqNZfgVPCK8N4bHYHFRfJiYuV+IqBNV5OhjKBGGxQJlTDgCGJxdRIExoFljuqBHENQhMJBAqBoOh6BIZJZOTFqgA5HCgTDgyGoKgVJh5ADKJmYLks-mCoAAROxcTh42YKlUwDoAI4ESAYer+1AQvLNEN5L0EOCcZrRuAEJBkTBISA1x2V6uoWMhAAsACZQAAqHL1xvN5pprkZ0AAeUwZAoyD9AZLqAq2BwRHVVEGWQQ0bwu5cCXMDTn5HiAH4XBFQARMBdUOMqOgr1wcDgkOg3KBSl3KlyYhwM8KCoC9rDvB8nw4C9QAPEgEGsZIAFV72aABhER0BjUAXDghAJ25f9PTAcAR0gJsOELYt+jELUaFPeczSQMYcDgCjlHAckdisPc2yrccuCPSNoCYCwiFfTh30-Nw-wqbFQBggADAASCJOFKABaVSEFKRScNAFSIh0rS1N0gRf0xFUwEAGXJQAAISQgBxFxpyaFo2nqDAqA-AhGK6BBICQYN+Cs0AMOfUAAEYXB9Jci0DMQNOoOh63qRASCIejOjzDVGmaVp2itECSGoEwHVtSBrBxJBLAAclDEgI1METarlf9qgAUVQXBUBcDrlAuUh0HqftgUrdQSCoCxuBKpgcBKyLrAEULwo4XsXOApi4uo5pQCSzoAqCor4hKvDIvKu0qomOr103UQd3g2qLFqtRjFau52rALqepccQHHG6ASpJEgUVAWrjxa0BBUdebXFEE0zU4T9WF9KjAwaNYQYuMGnTc2qlpC-hqlW0AAGYXFIhtyORtGV1oyBtSAxjkGOjUvJHc6AlcS7qrqvQ2M-DiuKeqLntekh3tC779F+-7ckBjHWFB2roHbZpaqhsRoFhkQqARhAkY4ZJtvR4Hldx9XrCAA

### 💻 Code

```ts
// Minimal reproduction showing the bug
class API any>> {
constructor(private methods: T) {}

// Method overloads for better DX
call(method: K): ReturnType;
call(method: K, ...args: Parameters): ReturnType;
call(method: K, ...args: any[]): ReturnType {
return this.methods[method](...args);
}
}

// Test with various method signatures
const api = new API({
// No parameters
getString: () => "hello",

// Required parameter
getNumber: (multiplier: number) => 42 * multiplier,

// Optional parameter
processData: (data: string, options?: { uppercase?: boolean }) =>
options?.uppercase ? data.toUpperCase() : data,

// Multiple parameters with optional
complexMethod: (a: number, b: string, c?: boolean) =>
c ? `${b}-${a}` : `${a}-${b}`
});

// ❌ BUG: Overload resolution fails

// Case 1: No parameters - should match first overload
const str = api.call('getString');
// Error: Expected 2 arguments, but got 1.

// Case 2: Optional parameter - fails
const data1 = api.call('processData', 'test');
// Error: Argument of type 'string' is not assignable to parameter of type 'never'.

// Case 3: Multiple parameters with optional
const result1 = api.call('complexMethod', 1, 'test');
// Error: Argument of type 'number' is not assignable to parameter of type 'never'.
```

### 🙁 Actual behavior

TypeScript fails to correctly resolve method overloads when using generic mapped types with Parameters utility type:

1. Methods with NO parameters: TypeScript expects 2 arguments instead of matching the first overload `call(method: K)`
- Error: "Expected 2 arguments, but got 1"

2. Methods with OPTIONAL parameters: TypeScript cannot determine that optional parameters can be omitted
- Error: "Argument of type 'string' is not assignable to parameter of type 'never'"

3. The overload resolution always picks the second overload even when it shouldn't

The generic constraint with `Parameters` appears to confuse the overload resolution mechanism.

### 🙂 Expected behavior

The overload resolution should work correctly based on the number and types of arguments:

1. When calling `api.call('getString')` with no additional arguments, TypeScript should match the FIRST overload and return type `string`

2. When calling `api.call('processData', 'test')` with optional parameters omitted, it should be valid and infer the correct types

3. Optional parameters should be truly optional in the method call

The compiler should be able to:
- Distinguish between the two overloads based on argument count
- Properly handle optional parameters in generic contexts
- Correctly infer return types based on the matched overload

This pattern is essential for type-safe API wrappers, RPC clients, and plugin systems.

### Additional information about the issue

This issue significantly impacts developer experience when building type-safe wrappers around dynamic method collections.

**Real-world use cases affected:**
- GraphQL/REST client generators
- RPC frameworks (tRPC, JSON-RPC)
- Database ORMs with dynamic query methods
- Plugin architectures with registered methods
- Testing utilities for creating typed mocks

**Current workarounds (all suboptimal):**
1. Use type assertions (`as any`) - loses type safety
2. Avoid overloads entirely - poor API ergonomics
3. Create individual wrapper methods - defeats the purpose of generic approach

**Related issues:**
- #47607 - Generic inference with Parameters utility type
- #26591 - Overload resolution with generic constraints
- #20732 - Overload gets lost in mapped type with conditional type

Without proper overload resolution, library authors must sacrifice either type safety or developer experience.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit der verlinkten TypeScript Playground-Reproduktion und untersuche die drei fehlschlagenden Aufrufe im Zusammenhang mit Überladungen, Parameters, ReturnType und optionalen Parametern. Vergleiche das Verhalten mit den verwandten Issues #47607, #26591 und #20732; abgeschlossen ist die Aufgabe, wenn die Aufrufe mit der erwarteten Argumentbehandlung und den erwarteten inferierten Rückgabetypen typgeprüft werden, abgesichert durch Compiler-Regressionstests.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
typescript
Bereich
compilers
Issue-Typ
Bug
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
30/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.