如何在评估字符串形式的TypeScript代码时捕获类型错误?
如何运行字符串形式的TypeScript代码并捕获类型错误
要同时实现字符串TS代码的执行和类型错误检测,不能只依赖transpile(它仅做转译不做类型检查),需要利用TypeScript的编译器API完成完整的类型校验,再执行合法代码。
核心思路
- 用TypeScript编译器API创建虚拟程序,将字符串代码模拟为文件输入
- 提取程序的诊断信息(类型错误、语法错误等)
- 无错误时转译代码并执行,有错误则返回错误信息
实现代码示例
import * as ts from 'typescript'; function evaluateTSCode(tsCode: string) { // 定义虚拟文件名,TS编译器需要关联文件路径 const fileName = 'virtual-code.ts'; // 创建编译程序,配置检查规则 const program = ts.createProgram([fileName], { target: ts.ScriptTarget.ESNext, strict: true, // 开启严格类型检查,可按需调整 noEmitOnError: true, // 存在错误时不生成输出代码 }, { // 自定义文件系统实现,让TS读取我们的字符串代码 readFile: () => tsCode, fileExists: () => true, getCurrentDirectory: () => '', getDirectories: () => [], getCanonicalFileName: (file) => file, useCaseSensitiveFileNames: () => true, }); // 获取所有预编译诊断信息(包含类型错误) const diagnostics = ts.getPreEmitDiagnostics(program); if (diagnostics.length > 0) { // 格式化错误信息 const errors = diagnostics.map(diagnostic => { if (diagnostic.code && diagnostic.messageText) { return `TS${diagnostic.code}: ${diagnostic.messageText}`; } return '未知TypeScript错误'; }); return { success: false, errors }; } // 转译合法代码 const emitResult = program.emit(fileName); const transpiledCode = emitResult.outputFiles?.[0]?.text; if (!transpiledCode) { return { success: false, errors: ['代码转译失败'] }; } // 执行转译后的JS代码 try { const result = eval(transpiledCode); return { success: true, result }; } catch (execError) { return { success: false, errors: [`运行时错误: ${execError.message}`] }; } } // 测试用例 // 带类型错误的代码 const errorCode = 'const str: string = 123;'; console.log(evaluateTSCode(errorCode)); // 输出: { success: false, errors: ['TS2322: Type 'number' is not assignable to type 'string'] } // 合法代码 const validCode = 'const str: string = "hello"; return str.length;'; console.log(evaluateTSCode(validCode)); // 输出: { success: true, result: 5 }
关键说明
- 虚拟文件系统:TypeScript编译器API基于文件系统设计,因此需要实现
CompilerHost的必要方法,让编译器能够读取我们的字符串代码。 - 诊断信息:
getPreEmitDiagnostics会返回所有编译前的错误,包括类型不匹配、语法错误等,完全覆盖TS的类型检查能力。 - 执行风险:使用
eval执行动态代码存在安全风险,若处理不可信来源的代码,需额外做安全隔离。 - 编译选项:可根据需求调整
ts.createProgram的第二个参数(编译选项),比如关闭strict、修改target等,适配不同的代码场景。
内容的提问来源于stack exchange,提问作者Gershom Maes
相关产品推荐
相关产品推荐

