microsoft / microsoft/TypeScript
Method overloads fail to resolve correctly when using mapped types with conditional generics and optional parameters
Dieses Issue hat noch niemand übernommen.
- 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
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Ö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