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

如何基于类中带指定装饰器的属性生成TypeScript联合类型

实现提取带特定装饰器属性的泛型类型

TypeScript的类型系统本身无法直接识别运行时装饰器,得结合元数据来实现这个需求,具体步骤如下:

1. 实现带元数据记录的装饰器

借助reflect-metadata库,让@Attribute()装饰器把属性名记录到类的元数据里:

import 'reflect-metadata';

// 定义唯一的元数据标识
const ATTRIBUTE_KEY = Symbol('attribute');

function Attribute() {
  return function(target: any, propertyKey: string) {
    // 读取已有属性列表,没有则初始化为空数组
    const existingAttrs = Reflect.getMetadata(ATTRIBUTE_KEY, target) || [];
    // 将当前属性名存入元数据
    Reflect.defineMetadata(ATTRIBUTE_KEY, [...existingAttrs, propertyKey], target);
  };
}

2. 定义泛型类型ExtractAttributes

通过读取类原型上的元数据,提取对应的属性名联合类型:

type ExtractAttributes<T extends new (...args: any[]) => any> = 
  (typeof Reflect.getMetadata(ATTRIBUTE_KEY, T.prototype))[number];

3. 测试示例

用你提供的Image类测试,就能得到预期的类型:

class Image {
  @Attribute()
  public id: number;

  @Attribute()
  public src: string;

  public alt: string;
}

type ImageAttributes = ExtractAttributes<typeof Image>;
// ImageAttributes 的类型为 "id" | "src",完全符合需求

注意事项

  • 需要先安装reflect-metadata:npm install reflect-metadata
  • 在tsconfig.json中开启以下选项:
    {
      "compilerOptions": {
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true
      }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 08:56:08