如何在编译时自动将TypeScript类型及子类型转换为JSON?
实现TypeScript类型到JSON结构的自动化转换
以下是三种实用的自动化实现方案,避免手动维护类型对应的JSON结构:
方案1:类型编程+运行时生成(简单易上手)
利用TypeScript的类型推导能力,结合辅助函数生成目标JSON结构,编译时就能保证结构与类型一致。
步骤1:定义类型转换的通用类型
// 递归将TS类型映射为目标JSON结构 type TypeToJson<T> = { [K in keyof T]: T[K] extends string ? "string" : T[K] extends number ? "number" : T[K] extends boolean ? "boolean" : T[K] extends object ? TypeToJson<T[K]> : "unknown"; // 兜底处理其他未覆盖的类型 };
步骤2:编写生成运行时对象的辅助函数
// 递归遍历占位对象,生成类型对应的JSON结构 function generateTypeJson<T>(obj: T): TypeToJson<T> { const result: Record<string, any> = {}; for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { const value = obj[key]; if (typeof value === 'object' && value !== null) { result[key] = generateTypeJson(value); } else { result[key] = typeof value; } } } return result as TypeToJson<T>; }
步骤3:使用示例
type B = { propX: string; }; type A = { prop1: string; prop2: B; }; // 创建符合类型结构的占位对象(仅用于类型推导,值不影响结果) const placeholderA: A = { prop1: '', prop2: { propX: '' } }; // 生成目标JSON结构 const jsonOfTypeA = generateTypeJson(placeholderA); // 输出结果:{ prop1: "string", prop2: { propX: "string" } }
优势:无需额外工具,TS类型检查会自动提醒占位对象与类型的不一致,避免遗漏变更。
方案2:自定义TypeScript Transformer(编译时自动生成)
通过编写TS编译转换器,在编译阶段直接从类型定义生成对应的JSON对象代码,完全自动化,无需维护占位对象。
核心思路
- 解析TS代码的AST(抽象语法树),定位目标类型别名(如
type A = ...) - 递归解析类型的属性和嵌套类型,生成对应的对象字面量代码
- 将生成的代码注入到编译后的JS文件中
注意:需要配置ts-loader、esbuild或rollup-plugin-typescript2等构建工具来启用自定义Transformer,适合中大型项目使用。
方案3:Node.js脚本代码生成(灵活可控)
编写脚本读取TS文件,解析类型定义后直接生成JSON文件,可集成到项目的构建流程中。
示例脚本
const ts = require('typescript'); const fs = require('fs'); // 读取目标TS文件 const sourceFile = ts.createSourceFile( './models.ts', fs.readFileSync('./models.ts', 'utf8'), ts.ScriptTarget.Latest, true ); // 递归解析类型节点 function parseTypeNode(node) { const result = {}; if (ts.isTypeLiteralNode(node)) { node.members.forEach(member => { if (ts.isPropertySignature(member)) { const propName = member.name.text; let propType = 'unknown'; if (ts.isStringKeywordTypeNode(member.type)) { propType = 'string'; } else if (ts.isNumberKeywordTypeNode(member.type)) { propType = 'number'; } else if (ts.isTypeReferenceNode(member.type)) { // 查找嵌套类型定义并递归解析 const nestedType = sourceFile.statements.find(s => ts.isTypeAliasDeclaration(s) && s.name.text === member.type.typeName.text ); if (nestedType) { propType = parseTypeNode(nestedType.type); } } result[propName] = propType; } }); } return result; } // 遍历AST找到目标类型并生成JSON sourceFile.statements.forEach(node => { if (ts.isTypeAliasDeclaration(node) && node.name.text === 'A') { const typeJson = parseTypeNode(node.type); fs.writeFileSync('./typeA.json', JSON.stringify(typeJson, null, 2)); } });
使用方式:将脚本保存为generate-type-json.js,在package.json中添加命令:
{ "scripts": { "generate-type-json": "node generate-type-json.js" } }
类型变更后运行npm run generate-type-json即可更新JSON文件。
内容的提问来源于stack exchange,提问作者Fred Johnson
相关产品推荐
相关产品推荐

