TypeScript如何通过泛型Key推导Interface属性类型并修复内部调用报错
问题原因
TypeScript 类型系统当前不支持在泛型函数内部自动关联「泛型参数K」和「对应Api[K]的参数类型」的绑定关系。它会独立推导api[apiName]为所有Api方法的联合类型、params为所有方法参数的联合类型,无法识别到两者始终对应同一个K,因此会抛出参数不匹配的错误,这个错误属于类型系统的局限性,你的业务逻辑本身是完全正确的。
解决方案
方案1:类型断言(推荐)
最简便的修复方式是对调用的方法做一次安全的类型断言,手动告诉TS两者的类型是匹配的,不会破坏外部调用的类型校验:
const api: Api; function callApi<K extends keyof Api>(apiName: K, ...params: Parameters<Api[K]>): ReturnType<Api[K]> { return (api[apiName] as (...args: Parameters<Api[K]>) => ReturnType<Api[K]>)(...params); }
修改后内部的类型报错会消失,同时外部调用的参数校验逻辑完全保留:
callApi('foo', 1); // 依旧会提示:类型'number'的参数不能赋值给类型'string'的参数 callApi('bar', '1'); // 依旧会提示:类型'string'的参数不能赋值给类型'number'的参数 callApi('baz'); // 调用正常
方案2:函数重载
如果不希望使用类型断言,也可以通过函数重载实现,但需要为每个Api的键单独定义重载,维护成本更高,适合Api结构固定且键数量少的场景:
function callApi(apiName: 'foo', p: string): number; function callApi(apiName: 'bar', p: number): string; function callApi(apiName: 'baz'): number[]; function callApi(apiName: keyof Api, ...params: any[]) { return api[apiName](...params); }
内容的提问来源于stack exchange,提问作者niminjie
相关产品推荐
相关产品推荐

