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

为何不创建类实例就无法遍历其属性?对应解决方案有哪些?

为什么无法直接遍历类获取实例属性?
  • 你在TypeScript类中写的name: string、colour: string属于类型标注,仅在编译阶段做类型校验用,不会生成任何运行时代码,编译后会被完全清除,运行时根本不存在这些标记。
  • 就算是纯JavaScript的类实例字段,也默认属于每个实例对象自身,既不会挂载到类构造函数(也就是你写的Animal本身)上,也不会挂载到Animal.prototype原型对象上。只有当你调用new Animal()创建实例时,才会在新生成的实例对象上初始化这些字段。
  • 你调用Object.keys(Animal)拿到的是挂载在类构造函数上的静态属性,和实例属性完全是两个维度的内容,自然拿不到name、colour这些实例属性的key。
对应解决方案

要实现单一位置统一管理所有Animal属性,不需要重复定义接口和属性列表,可选以下方案:

方案1:用常量统一定义属性列表,反向推导类型

该方案属性定义只有一个数据源,修改、新增属性只需要改常量数组即可,完全不会出现类型和运行时属性不一致的问题。

// 统一定义所有属性,修改只需要改这里
const ANIMAL_PROPERTIES = ['name', 'colour'] as const;
type AnimalProperty = typeof ANIMAL_PROPERTIES[number];

export class Animal {
  // 直接用推导出来的类型约束类属性,不需要重复写key
  [key in AnimalProperty]: string;

  constructor(init: string[]) {
    // 可以直接遍历属性列表赋值,避免手写漏项
    ANIMAL_PROPERTIES.forEach((prop, index) => {
      this[prop] = init[index];
    });
  }
}

// 需要遍历属性的地方,直接用这个常量即可
for (const key of ANIMAL_PROPERTIES) {
  console.log(key); // 会依次输出 name、colour
}

方案2:将属性列表挂载为类的静态属性

如果希望属性和类绑定更紧密,可以直接把列表定义为类的静态成员:

export class Animal {
  // 静态属性列表,全局可访问
  static readonly PROPERTIES = ['name', 'colour'] as const;

  name: string;
  colour: string;

  constructor(init: string[]) {
    this.name = init[0];
    this.colour = init[1]; // 注意示例代码中此处误写为color,会导致类型报错
  }
}

// 遍历直接取静态属性即可
for (const key of Animal.PROPERTIES) {
  console.log(key);
}

以上两种方案都可以同时满足类型校验和运行时遍历的需求,只有一个属性管理入口,不需要额外创建重复的interface。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:36:01