如何使用TypeScript Compiler API将type转换为带class-validator声明的class
TypeScript type 转带 class-validator 装饰器的 class 实现方案
你可以直接使用TypeScript官方提供的Compiler API完成这个需求,这是兼容性和扩展性最好的实现方式,具体步骤如下:
核心实现步骤
- 安装依赖并初始化编译实例
首先安装typescript依赖,创建编译程序加载你要处理的目标文件,获取对应的AST节点:import * as ts from 'typescript'; const targetFilePath = './你的目标文件路径.ts'; const program = ts.createProgram([targetFilePath], { strict: true, }); const sourceFile = program.getSourceFile(targetFilePath)!; - 遍历AST匹配类型别名节点
遍历源文件的AST节点,匹配type xxx = {}格式的类型别名声明,你说的typeNode就是类型别名下的type属性,当它是对象字面量类型时就能拿到所有属性信息:ts.forEachChild(sourceFile, (node) => { // 匹配类型别名声明,且类型是对象字面量 if (ts.isTypeAliasDeclaration(node) && ts.isTypeLiteralNode(node.type)) { const className = node.name.getText(); // 过滤出所有属性 const properties = node.type.members.filter(ts.isPropertySignature); // 后续生成class逻辑写在这里 } }); - 维护类型和装饰器的映射关系
提前定义TS基础类型对应class-validator装饰器的映射表,遇到对应类型直接匹配即可,可选属性可以额外加@IsOptional()装饰器:const typeDecoratorMap: Record<string, string> = { string: '@IsString()', number: '@IsNumber()', boolean: '@IsBoolean()', Array: '@IsArray()', // 可自行扩展联合类型、自定义类型等映射规则 }; - 生成并输出class代码
你可以直接拼接字符串生成代码,也可以用TS自带的factory和printer生成规范的代码节点,避免语法错误:const factory = ts.factory; // 生成class声明节点 const classNode = factory.createClassDeclaration( undefined, factory.createIdentifier(className), undefined, undefined, properties.map((prop) => { const propTypeName = prop.type!.getText(); const decorators = []; // 可选属性加@IsOptional() if (prop.questionToken) { decorators.push( factory.createDecorator( factory.createCallExpression(factory.createIdentifier('IsOptional'), undefined, []) ) ); } // 加对应类型的装饰器 decorators.push( factory.createDecorator( factory.createCallExpression( factory.createIdentifier(typeDecoratorMap[propTypeName].replace(/^@|\(\)$/g, '')), undefined, [] ) ) ); // 生成属性节点 return factory.createPropertyDeclaration( decorators, prop.name.getText(), undefined, prop.type, undefined ); }) ); // 打印为代码文本 const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); const outputCode = printer.printNode(ts.EmitHint.Unspecified, classNode, sourceFile); console.log(outputCode);
简化方案
如果不想处理底层Compiler API逻辑,可以用封装好的ts-morph库,它的API更简单易用,十几行代码就能完成相同的转换逻辑。如果只是处理简单固定的类型,也可以直接写正则匹配替换,不过这种方式不支持复杂的嵌套、联合类型场景。
内容的提问来源于stack exchange,提问作者klaus bai
相关产品推荐
相关产品推荐

