TypeScript父类装饰器字段未加入INCLUDED_FIELDS问题求助
问题根源分析
你遇到的问题核心在于父类的包含字段没有被子类实例继承读取:
当你在Base类的name属性上使用@JsonInclude装饰器时,该字段被添加到了以"Base"为键的INCLUDED_FIELDS映射条目里。但当实例化Staff子类时,this.constructor.name返回的是"Staff",所以原toJSON方法只会读取"Staff"对应的字段列表,完全忽略了父类Base中定义的包含字段,导致name没有被加入最终的JSON对象。
另外,虽然你的装饰器实现对于实例属性的目标对象处理是正确的(target是类的原型,target.constructor指向类本身),但缺少了原型链字段合并的逻辑,这是关键遗漏点。
解决方案
修改Base类的toJSON方法,遍历实例的原型链,收集所有父类(包括当前类)的包含字段,再统一过滤属性。同时优化装饰器的命名可读性:
// base.ts 修改后的代码 export const INCLUDED_FIELDS = new Map<string, string[]>(); export function JsonInclude(target: any, propertyKey: string){ // 获取当前属性所属的类构造函数 const cls = target.constructor; const clsName = cls.name; let list: string[]; if (INCLUDED_FIELDS.has(clsName)) { list = INCLUDED_FIELDS.get(clsName)!; } else { list = []; INCLUDED_FIELDS.set(clsName, list); } list.push(propertyKey); } export default class Base{ @JsonInclude public name: string; // 补充构造函数初始化name,避免字段未定义 constructor(name: string) { this.name = name; } toJSON(): { [name: string]: any } { const json: { [name: string]: any } = {}; const includedFields = new Set<string>(); // 遍历原型链,收集所有继承层级的包含字段 let currentProto = Object.getPrototypeOf(this); while (currentProto !== null) { const clsName = currentProto.constructor.name; const fields = INCLUDED_FIELDS.get(clsName); if (fields) { fields.forEach(field => includedFields.add(field)); } currentProto = Object.getPrototypeOf(currentProto); } // 过滤并添加符合条件的属性 Object.getOwnPropertyNames(this) .filter(name => includedFields.has(name)) .forEach(name => { json[name] = this[name]; }); return json; } }
staff.ts可以保持原样,补充构造函数调用父类初始化:
// staff.ts import Base, { JsonInclude } from './base'; export default class Staff extends Base { @JsonInclude public salary: number = 1000; @JsonInclude public level: number = 1; @JsonInclude public comment:string = ""; constructor(name: string) { super(name); } }
测试验证
执行以下代码:
const staff = new Staff("Alice"); console.log(JSON.stringify(staff));
会输出预期结果:
{"name":"Alice","salary":1000,"level":1,"comment":""}
额外优化说明
- 使用
Set存储字段,避免父类和子类出现同名字段时重复添加 - 遍历原型链的逻辑支持多层继承场景,不管继承多少层级都能正确收集所有父类的包含字段
- 补充构造函数初始化,避免
name字段出现undefined
内容的提问来源于stack exchange,提问作者armnotstrong
相关产品推荐
相关产品推荐

