如何在TypeScript中实现类的条件继承创建模式?
实现动态代理类的解决方案
你要实现的这种动态代理类,在JS/TS里没法直接在构造函数里修改继承关系——因为类的继承是定义阶段就固定的。不过可以用下面几种方式满足核心需求:让基类实例根据参数访问对应类的成员,同时支持传递参数给目标类。
方案1:动态修改实例原型(支持参数传递)
通过修改实例的原型链,让基类实例继承目标类的原型方法,同时调用目标类构造函数并传递参数:
class A { constructor(public param?: any) {} classAFunction() { console.log('Class A', this.param) } } class B { constructor(public param?: any) {} classBFunction() { console.log('Class B', this.param) } } class C { constructor(classToInherit: string, ...args: any[]) { const TargetClass = classToInherit === 'A' ? A : B; // 调用目标类构造函数,传递参数并拷贝实例属性 Object.assign(this, new TargetClass(...args)); // 修改原型链,让实例继承目标类的原型方法 Object.setPrototypeOf(this, TargetClass.prototype); } } // 使用示例 const c1 = new C('A', 'hello A'); c1.classAFunction(); // 输出: Class A hello A const c2 = new C('B', 'hello B'); c2.classBFunction(); // 输出: Class B hello B
方案2:工厂函数(推荐,类型更友好)
如果不需要严格的class C结构,用工厂函数更简洁,TypeScript的类型推断也更准确:
class A { constructor(public param?: any) {} classAFunction() { console.log('Class A', this.param) } } class B { constructor(public param?: any) {} classBFunction() { console.log('Class B', this.param) } } // 函数重载确保类型提示准确 function createProxy(className: 'A', ...args: ConstructorParameters<typeof A>): A; function createProxy(className: 'B', ...args: ConstructorParameters<typeof B>): B; function createProxy(className: string, ...args: any[]): A | B { switch(className) { case 'A': return new A(...args); case 'B': return new B(...args); default: throw new Error('无效的类名'); } } // 使用示例 const aProxy = createProxy('A', 'test A'); aProxy.classAFunction(); // 输出: Class A test A const bProxy = createProxy('B', 'test B'); bProxy.classBFunction(); // 输出: Class B test B
方案3:直接混入成员到实例
如果不想修改原型链,也可以把目标类的所有属性和方法直接绑定到基类实例上:
class A { constructor(public param?: any) {} classAFunction() { console.log('Class A', this.param) } } class B { constructor(public param?: any) {} classBFunction() { console.log('Class B', this.param) } } class C { constructor(classToInherit: string, ...args: any[]) { const instance = classToInherit === 'A' ? new A(...args) : new B(...args); // 拷贝实例属性 Object.assign(this, instance); // 拷贝原型方法并绑定当前实例 const proto = Object.getPrototypeOf(instance); Object.getOwnPropertyNames(proto).forEach(key => { if (key !== 'constructor') { this[key] = proto[key].bind(this); } }); } } // 使用示例 const c1 = new C('A', 'hello'); c1.classAFunction(); // 输出: Class A hello
内容的提问来源于stack exchange,提问作者Mehul Chaturvedi
相关产品推荐
相关产品推荐

