microsoft / microsoft/TypeScript

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

未关闭
#62,377 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
Needs More Info
主要语言
Go
星标
111k
派生
14.3k
平均合并
2 天 4 小时
30 天内合并 PR
132

描述

### 🔎 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.

贡献指南

打开贡献指南

调研方向

从链接的 TypeScript Playground 重现开始,检查涉及重载、Parameters、ReturnType 和可选参数的三个失败调用。将行为与相关 issue #47607、#26591 和 #20732 进行比较;当这些调用能够按照预期处理参数并推断出预期的返回类型,通过类型检查,并由 compiler regression coverage 提供保障时,即表示完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
typescript
领域
compilers
Issue 类型
缺陷
难度
5/5
预计耗时
一周以上
活跃度
停滞
描述清晰度
基本清楚
新手友好度
30/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。