TypeScript带剩余参数的函数重载调用报错及类型推断问题
解决方案
核心思路是通过类型映射表统一管理每个选择器对应的参数元组和返回值类型,再结合泛型实现强类型约束,既解决调用时的TS2556错误,又完整保留参数校验和类型推断能力。
步骤1:定义选择器类型映射表
先创建一个接口,把每个选择器的参数列表和返回值类型一一对应:
// 假设MyInterface已定义 interface MyInterface { /* ... */ } interface AuthSelectorMap { selector1: { args: []; return: string[] }; selector2: { args: [string]; return: boolean }; selector3: { args: []; return: boolean }; selector4: { args: []; return: string }; selector5: { args: []; return: MyInterface }; selector6: { args: []; return: string }; } type IAuthSelectors = keyof AuthSelectorMap;
步骤2:重构getAuthState函数
用泛型约束选择器和参数,替代手动写重复的重载:
function getAuthState<K extends IAuthSelectors>( selector: K, ...args: AuthSelectorMap[K]['args'] ): AuthSelectorMap[K]['return'] { // 这里写你的返回逻辑,比如从状态中获取对应值 return {} as AuthSelectorMap[K]['return']; }
步骤3:重构useAuthSelector函数
同样用泛型关联选择器和参数,调用getAuthState时参数类型完全匹配,不会触发TS2556错误:
function useAuthSelector<K extends IAuthSelectors>( selector: K, ...args: AuthSelectorMap[K]['args'] ): AuthSelectorMap[K]['return'] { const authState = getAuthState(selector, ...args); // 无类型错误 // 这里可以添加自定义逻辑,比如监听状态变化等 return authState; }
效果验证
- 合法调用会自动推断返回值类型:
const s1 = useAuthSelector('selector1'); // s1类型为string[] const s2 = useAuthSelector('selector2', 'test'); // s2类型为boolean - 非法调用会直接触发类型错误:
getAuthState('selector1', 'param1'); // 报错:参数数量不匹配 useAuthSelector('selector2'); // 报错:缺少必需的string参数
为什么原来的方案有问题
- TS2556错误原因:原代码中
useAuthSelector的实现签名用unknown[]接收剩余参数,而getAuthState的重载都是固定参数列表,TypeScript无法确认unknown[]是否匹配某个重载的参数,因此报错。 - 添加剩余参数重载的问题:如果给
getAuthState加function getAuthState(selector: IAuthSelectors, ...args: unknown[]): unknown的重载,TypeScript会优先匹配这个宽松的重载,导致其他严格的重载失效,从而丢失参数校验能力。
内容的提问来源于stack exchange,提问作者Sergio Tx
相关产品推荐
相关产品推荐

