microsoft / microsoft/TypeScript
Method overloads fail to resolve correctly when using mapped types with conditional generics and optional parameters
Nadie ha tomado este issue todavía.
- Lenguaje dominante
- Go
- Estrellas
- 111k
- Forks
- 14.3k
- Merge medio
- 2 d 4 h
- PR fusionados (30 d)
- 132
Descripción
### 🔎 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.
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Línea de trabajo
Comienza con la reproducción enlazada en TypeScript Playground e inspecciona las tres llamadas que fallan relacionadas con sobrecargas, Parameters, ReturnType y parámetros opcionales. Compara el comportamiento con los issues relacionados #47607, #26591 y #20732; se considera terminado cuando las llamadas pasan la comprobación de tipos con el manejo esperado de los argumentos y los tipos de retorno inferidos, respaldadas por cobertura de regresión del compilador.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- typescript
- Área
- compilers
- Tipo de issue
- Error
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Estado de actividad
- Estancado
- Claridad
- Bastante claro
- Aptitud para principiantes
- 30/100