TypeScript中如何通过装饰器让父类获取子类所有属性数据?
解决方案一:装饰器+元数据实现
要实现你需要的效果,用TypeScript的装饰器结合元数据就能搞定,具体步骤如下:
- 配置TypeScript编译选项
因为要用到元数据功能,需要在tsconfig.json中开启相关配置:
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } }
同时需要安装reflect-metadata依赖:
npm install reflect-metadata
- 实现
@propertydecorator装饰器
这个装饰器的作用是把被标记的属性名称存入类的元数据中,方便父类动态读取:
import 'reflect-metadata'; // 定义元数据的唯一标识key const CALC_PROPS_KEY = Symbol('calcProps'); export function propertydecorator(target: any, propertyKey: string) { // 获取已标记的属性列表,无则初始化空数组 const existingProps = Reflect.getMetadata(CALC_PROPS_KEY, target) || []; // 将当前属性名加入列表 existingProps.push(propertyKey); // 更新元数据 Reflect.defineMetadata(CALC_PROPS_KEY, existingProps, target); }
- 修改抽象父类
Parent
父类的calc方法通过元数据获取子类标记的属性,再从实例上取值计算:
abstract class Parent { constructor() {} calc() { // 从子类原型中获取被装饰器标记的属性列表 const props = Reflect.getMetadata(CALC_PROPS_KEY, this.constructor.prototype) as string[]; if (!props || props.length !== 2) { throw new Error('子类必须标记两个属性用于计算'); } // 从实例上提取属性值并计算 const [a, b] = props.map(prop => this[prop]); console.log("result: " + a * b); } }
- 子类
Children实现
和你给出的代码基本一致,只需补充父类构造函数调用:
class Children extends Parent { @propertydecorator a: number; @propertydecorator b: number; constructor(no1: number, no2: number) { super(); // 必须调用父类构造函数 this.a = no1; this.b = no2; } }
- 验证效果
const children = new Children(2, 4); children.calc(); // 输出:result: 8
解决方案二:抽象属性约束(无需装饰器)
如果不需要用装饰器做额外逻辑,也可以通过父类定义抽象属性,强制子类实现,父类直接访问即可:
abstract class Parent { // 定义抽象属性,子类必须实现 abstract a: number; abstract b: number; constructor() {} calc() { console.log("result: " + this.a * this.b); } } class Children extends Parent { a: number; b: number; constructor(no1: number, no2: number) { super(); this.a = no1; this.b = no2; } } // 使用验证 const children = new Children(2, 4); children.calc(); // 输出:result: 8
这种方式更简洁,TypeScript会在编译阶段检查子类是否实现了抽象属性,避免运行时错误。
内容的提问来源于stack exchange,提问作者Chris H
相关产品推荐
相关产品推荐

