如何通过TypeScript AST/TypeChecker获取带完整属性的已解析类型
实现方案
你之前只拿到AST层面的信息,是因为没有调用TypeScript编译器的类型检查器能力,TS Playground展示的是类型推导完成后的结果,需要基于TS官方Compiler API的TypeChecker实现提取:
核心逻辑
- 不要仅解析语法树,要初始化TS编译实例后获取类型检查器,拿到推导完成的Type对象,才能得到包含继承、泛型实例化、类型别名展开后的完整信息。
- 对Type对象递归遍历所有属性,即可得到和Playground完全一致的结构化类型数据。
- 如果你习惯使用ts-morph,可直接调用其封装的
getType()相关方法,本质也是调用底层TS的TypeChecker能力,不用手动初始化编译项目。
关键实现代码
先安装依赖:npm install typescript
参考代码示例:
import * as ts from 'typescript'; // 1. 初始化TS编译项目,配置和你项目的tsconfig保持一致 const program = ts.createProgram(['目标文件路径.ts'], { strict: true }); const typeChecker = program.getTypeChecker(); // 2. 定位到你要提取类型的声明节点(示例为找指定名称的接口/类型别名) const sourceFile = program.getSourceFile('目标文件路径.ts')!; let targetTypeNode: ts.InterfaceDeclaration | ts.TypeAliasDeclaration | undefined; ts.forEachChild(sourceFile, node => { if ((ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)) && node.name.text === '你要提取的类型名') { targetTypeNode = node; } }); if (!targetTypeNode) throw new Error('未找到目标类型'); // 3. 获取推导完成的完整类型对象 const targetType = typeChecker.getTypeAtLocation(targetTypeNode); // 4. 遍历所有属性(包含继承得到的属性) const allProperties = typeChecker.getPropertiesOfType(targetType); // 5. 格式化得到结构化的类型信息 const parsedType = allProperties.map(propSymbol => { const propType = typeChecker.getTypeOfSymbolAtLocation(propSymbol, targetTypeNode!); return { name: propSymbol.name, type: typeChecker.typeToString(propType), isOptional: !!(propSymbol.flags & ts.SymbolFlags.Optional), isReadonly: !!(propSymbol.flags & ts.SymbolFlags.Readonly) }; }); console.log(parsedType);
扩展适配建议
如果需要处理联合类型、交叉类型、嵌套对象、泛型等复杂类型,可通过判断Type的flags属性区分类型类别,递归拆解嵌套结构即可。拿到完整的结构化类型信息后,你就可以对应实现JS对象和MongoDB BSON格式的自动转换逻辑,比如日期类型、数组类型、ObjectId类型的自动适配。
内容的提问来源于stack exchange,提问作者Val
相关产品推荐
相关产品推荐

