TypeScript如何获取类的属性与类型(类似Python的__annotations__)
在TypeScript中获取类属性及类型(类似Python的__annotations__)
TypeScript的类型信息编译后会被擦除,无法直接在运行时获取,但可以通过以下几种方式实现类似需求:
1. 用装饰器结合元数据收集
借助reflect-metadata库和TypeScript装饰器语法,能在类属性上标记并存储类型元数据,运行时读取这些信息。
步骤:
- 安装依赖:
npm install reflect-metadata - 修改tsconfig.json开启相关配置:
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } } - 实现工具代码:
import 'reflect-metadata'; // 属性装饰器,自动收集类型元数据 function Prop(target: any, propertyKey: string) { const type = Reflect.getMetadata('design:type', target, propertyKey); const props = Reflect.getMetadata('class:props', target.constructor) || {}; props[propertyKey] = type; Reflect.defineMetadata('class:props', props, target.constructor); } // 获取类属性类型的工具函数 function sometool(cls: any) { return Reflect.getMetadata('class:props', cls) || {}; } class AnotherClass {} class A { @Prop public k: string; @Prop public o: number; @Prop public s: AnotherClass; } console.log(sometool(A)); // 输出:{ k: [Function: String], o: [Function: Number], s: [class AnotherClass] }
2. 自定义TypeScript转换器在编译阶段生成信息
编写自定义转换器,编译时扫描类的属性类型,自动为类添加包含类型信息的静态属性,运行时直接调用。
示例效果:
编译后自动生成类似代码:
class A { public k: string; public o: number; public s: AnotherClass; static __annotations__ = { k: String, o: Number, s: AnotherClass }; } function sometool(cls: any) { return cls.__annotations__; }
这种方式无需运行时依赖,但需要配置TypeScript编译时使用自定义转换器,适合工程化场景。
3. 用代码生成工具预生成类型信息
利用ts-morph这类操作TypeScript AST的工具,在开发阶段扫描源码,生成包含类属性类型的辅助文件,运行时直接导入使用。
示例:
import { Project } from 'ts-morph'; const project = new Project(); const sourceFile = project.addSourceFileAtPath('./src/A.ts'); const classA = sourceFile.getClass('A'); const annotations: Record<string, string> = {}; classA?.getProperties().forEach(prop => { const typeName = prop.getType().getText(); annotations[prop.getName()] = typeName; }); // 生成辅助文件 project.createSourceFile('./src/annotations.ts', ` export const AAnnotations = ${JSON.stringify(annotations)}; `).save();
运行时导入AAnnotations即可获取属性类型信息。
注意事项
- 基础类型(string/number等)运行时对应
String/Number构造函数,注意区分原始类型和包装对象。 - 自定义类的类型可直接获取到类的构造函数引用。
- 装饰器方案适合轻量场景,转换器和代码生成方案更适配复杂工程,无需运行时依赖。
内容的提问来源于stack exchange,提问作者Felipe Buccioni
相关产品推荐
相关产品推荐

