You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中通过反射获取所有属性(含未定义属性)?

解决方法:从类的元数据而非实例获取必填属性

当然可以!你遇到的问题根源在于,for...in循环只能遍历实例自身存在的可枚举属性,如果POST过来的对象没有包含name这类必填属性,实例上就不会有这个键,自然遍历不到。而静态反射的思路是直接从类的定义层面获取所有标记了required元数据的属性,完全不受实例是否初始化这些属性的影响。

具体实现步骤

  1. 从类的原型获取所有属性:类的属性定义(包括被装饰器标记的)会存在类的原型上,我们可以用Object.getOwnPropertyNames获取这些属性,再排除掉默认的constructor。
  2. 筛选带有required元数据的属性:对每个属性,用Reflect.hasMetadata检查是否存在我们定义的requiredSymbol元数据。
  3. 验证实例的必填属性:不管实例是否包含该属性,都能基于筛选出的必填列表进行验证。

修改后的代码示例

let requiredSymbol = Symbol('required');
function required() { 
  return Reflect.metadata(requiredSymbol, null); 
}
class Person { 
  @required()
  name: string; 

  @required()
  age: number;
}

// 模拟POST过来的对象(缺少name属性)
let p = { age: 25 }; // 实际场景中可能是JSON.parse后的对象

// 1. 获取Person类的所有实例属性(排除constructor)
const classProperties = Object.getOwnPropertyNames(Person.prototype).filter(prop => prop !== 'constructor');

// 2. 筛选并验证必填属性
classProperties.forEach(prop => {
  if (Reflect.hasMetadata(requiredSymbol, Person.prototype, prop)) {
    // 验证逻辑:检查实例是否缺少该属性,或属性值为空
    if (p[prop] === undefined || p[prop] === null) {
      throw new Error(`必填属性 ${prop} 未提供!`);
    }
    console.log(`属性 ${prop} 验证通过`);
  }
});

关键说明

  • 确保你的TypeScript编译选项已经开启了experimentalDecorators和emitDecoratorMetadata,否则元数据功能无法正常工作。
  • 这种方式是静态反射的典型应用:直接从类的定义中提取元数据,而不需要依赖实例的状态,完美解决了POST对象缺少属性时无法验证的问题。

内容的提问来源于stack exchange,提问作者williamsandonz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:03:00