如何在TypeScript中为接口增量扩展重载方法?
TypeScript接口增量扩展重载方法的问题解决
问题说明
直接在接口内声明多个重载签名是可行的:
interface Functions { size<T>(a: T[]): number size<T>(o: Record<string, T>): number }
但如果想通过「先声明空接口,再继承多个含单独重载的接口」这种增量扩展方式实现时,会触发报错:
报错代码
interface Functions {} interface ArrayFunctions { size<T>(a: T[]): number } interface ObjectFunctions { size<T>(o: Record<string, T>): number } interface Functions extends ArrayFunctions, ObjectFunctions {}
报错信息(翻译后)
接口'Functions'无法同时扩展类型'ArrayFunctions'和'ObjectFunctions'。
类型'ArrayFunctions'和'ObjectFunctions'的命名属性'size'不相同。ts(2320)
需求是:声明Functions接口时无法预知所有重载方法,需要后续增量添加。
解决方案
TypeScript不支持通过继承多个接口来合并同名函数的重载,正确的做法是用接口声明合并来实现增量扩展:
同一作用域下的实现
直接多次声明Functions接口,TypeScript会自动合并所有重载签名:
// 初始空接口 interface Functions {} // 增量添加数组类型的size重载 interface Functions { size<T>(a: T[]): number } // 增量添加对象类型的size重载 interface Functions { size<T>(o: Record<string, T>): number }
合并后的Functions接口效果和直接声明所有重载完全一致。
跨模块的实现
如果需要在不同文件中增量扩展,可以使用模块声明合并:
// 初始文件(比如functions.ts) export interface Functions {} // 另一个文件(比如array-functions.ts) import { Functions } from './functions' declare module './functions' { interface Functions { size<T>(a: T[]): number } } // 第三个文件(比如object-functions.ts) import { Functions } from './functions' declare module './functions' { interface Functions { size<T>(o: Record<string, T>): number } }
原理说明
当你通过继承多个接口时,每个接口中的size会被视为独立的函数成员,而非重载的一部分。TypeScript会认为这是两个冲突的同名属性,因此抛出错误。而直接合并同名接口时,TypeScript会把所有同名函数签名合并成一个重载列表,这才符合增量添加重载的需求。
内容的提问来源于stack exchange,提问作者Alex Craft
相关产品推荐
相关产品推荐

