TypeScript中如何实现类方法复用 寻求更优的原型链兼容方案
TypeScript 共享接口方法到多个类的优雅实现
方案1:抽象基类继承(最推荐)
通过抽象基类统一实现接口方法,后续业务类仅需继承基类即可自动获得原型链上的方法,全程类型安全。
interface SayName { name: string; say(): string; } function say(this: SayName) { return this.name; } // 抽象基类统一实现接口 abstract class SayNameBase implements SayName { abstract name: string; say() { return say.call(this); } } // 业务类仅需继承基类,无需额外写方法声明 export class Hello extends SayNameBase { name = "hello"; }
特点:
- 符合TS原生语法,无额外黑魔法
- say方法天然挂载在原型链上,和原生类方法表现完全一致
- 类型校验全程生效,子类漏写name属性会直接抛出类型错误
方案2:类装饰器(适合无需修改继承链的场景)
如果不想改动现有类的继承结构,可以用类装饰器批量挂载原型方法,同时自动合并类型定义。
interface SayName { name: string; say(): string; } function say(this: SayName) { return this.name; } type Constructor<T = {}> = new (...args: any[]) => T; // 装饰器自动给类原型挂载say方法,同时合并类型 function AddSayMethod<T extends Constructor<{name: string}>>(Base: T) { Base.prototype.say = say; return Base as T & Constructor<SayName>; } // 用装饰器修饰业务类即可,无需额外实现接口 @AddSayMethod export class Hello { name = "hello"; }
特点:
- 无需修改类的继承链,对现有业务代码侵入性更低
- 适合需要给多个零散类追加通用方法的场景
- 方法同样挂载在原型链上,类型自动推导无需额外声明接口合并
原写法的不足
- 类内直接赋值
say = say的写法:方法会成为每个实例的自有属性,不会挂载到原型链,每个实例都会单独存储一份方法副本,内存占用更高,也无法通过修改原型批量调整方法实现。 - 手动给原型赋值加接口合并的写法:功能符合要求,但每个类都要单独写一次接口合并,重复代码多,容易漏写导致类型报错。
内容的提问来源于stack exchange,提问作者Gabriel Machado
相关产品推荐
相关产品推荐

