如何通过TypeScript Compiler API在编译时添加导入语句?
如何用TypeScript Compiler API在编译代码中添加导入语句
要实现这个需求,核心是修改TypeScript的抽象语法树(AST),再用Printer输出修改后的AST。以下是两种可行的实现方式:
方法一:直接修改单个源文件并输出
如果只是处理单个文件并生成目标代码,可以直接解析源文件、修改AST后打印:
import * as ts from 'typescript'; // 1. 读取并解析源文件为AST const sourceCode = `// index.ts export * from './user.repository'`; const sourceFile = ts.createSourceFile( 'index.ts', sourceCode, ts.ScriptTarget.Latest, true ); // 2. 创建需要添加的导入节点 const createImportNode = (modulePath: string) => ts.factory.createImportDeclaration( undefined, // 修饰符(如export) undefined, // 导入子句(如import { xxx }) ts.factory.createStringLiteral(modulePath), // 模块路径 undefined // 断言子句 ); const saveImport = createImportNode('./save.user.repository.extension'); const deleteImport = createImportNode('./delete.user.repository.extension'); // 3. 构造新的语句数组:把新导入放在最前面,拼接原文件语句 const updatedStatements = [saveImport, deleteImport, ...sourceFile.statements]; // 4. 生成修改后的源文件(TS AST不可变,必须创建新对象) const updatedSourceFile = ts.factory.updateSourceFile( sourceFile, updatedStatements, sourceFile.isDeclarationFile, sourceFile.referencedFiles, sourceFile.typeReferenceDirectives, sourceFile.hasNoDefaultLib, sourceFile.libReferenceDirectives ); // 5. 打印修改后的AST const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); const outputCode = printer.printFile(updatedSourceFile); console.log(outputCode);
方法二:在编译流程中用自定义Transformer批量处理
如果需要在tsc编译过程中自动为指定文件添加导入,可通过自定义Transformer扩展编译流程:
import * as ts from 'typescript'; // 定义自定义Transformer:仅处理目标文件 function addImportsTransformer(program: ts.Program): ts.TransformerFactory<ts.SourceFile> { return (context) => { return (sourceFile) => { // 只处理index.ts文件,避免全局修改 if (sourceFile.fileName.endsWith('index.ts')) { const createImportNode = (modulePath: string) => ts.factory.createImportDeclaration( undefined, undefined, ts.factory.createStringLiteral(modulePath), undefined ); const newImports = [ createImportNode('./save.user.repository.extension'), createImportNode('./delete.user.repository.extension') ]; // 更新语句数组并返回新的源文件 const updatedStatements = [...newImports, ...sourceFile.statements]; return ts.factory.updateSourceFile(sourceFile, updatedStatements); } // 其他文件直接返回原AST return sourceFile; }; }; } // 通过Compiler API启动编译并应用Transformer const compilerOptions = { target: ts.ScriptTarget.Latest, module: ts.ModuleKind.CommonJS }; const program = ts.createProgram(['index.ts'], compilerOptions); const emitResult = program.emit(undefined, undefined, undefined, undefined, { before: [addImportsTransformer(program)] // 编译前应用Transformer }); // 输出编译错误(如果有) if (emitResult.emitSkipped) { const diagnostics = [...ts.getPreEmitDiagnostics(program), ...emitResult.diagnostics]; diagnostics.forEach(d => { const msg = ts.flattenDiagnosticMessageText(d.messageText, '\n'); console.error(`${d.file?.fileName || 'unknown'}:${d.start || 0}:${d.length || 0} - ${msg}`); }); }
你之前用ts.createPrinter失败的原因
你直接打印了未修改的原AST,没有先通过updateSourceFile生成包含新导入节点的AST,所以输出内容和原代码一致。必须先修改AST结构,再打印修改后的版本。
内容的提问来源于stack exchange,提问作者danixl30 ct
相关产品推荐
相关产品推荐

