You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用TypeScript Compiler API为函数添加前置注释

用TypeScript Compiler API给函数自动添加注释的正确姿势

踩过这个坑的人来给你支个招:直接修改SourceFile.statements的方式只能处理顶层函数,而且TypeScript的AST节点本质是不可变对象,硬改容易出各种奇怪的问题。更靠谱的做法是用官方的Transformer API来遍历并修改AST,既能覆盖所有函数(包括嵌套的),又能保证代码生成的正确性。

完整实现代码

下面是可以直接跑的示例,会给所有函数(函数声明、函数表达式、箭头函数)添加统一的注释:

import * as ts from 'typescript';
import * as fs from 'fs';

// 配置编译选项
const compilerOptions: ts.CompilerOptions = {
  target: ts.ScriptTarget.ESNext,
  module: ts.ModuleKind.CommonJS,
};

// 要处理的源文件路径
const inputFilePath = './your-input-file.ts';
const outputFilePath = './your-output-file.js';

// 创建Program实例
const program = ts.createProgram([inputFilePath], compilerOptions);
const sourceFile = program.getSourceFiles().find(file => !file.isDeclarationFile)!;

// 定义Transformer:遍历AST并添加注释
function addFunctionCommentsTransformer(context: ts.TransformationContext): ts.Transformer<ts.SourceFile> {
  return (node: ts.SourceFile) => {
    // 递归遍历所有节点的访问器
    const visitor: ts.Visitor = (node) => {
      // 匹配所有类型的函数节点
      if (
        ts.isFunctionDeclaration(node) ||
        ts.isFunctionExpression(node) ||
        ts.isArrowFunction(node)
      ) {
        // 给函数节点添加前置注释
        // 第一个参数是目标节点,第二个是注释类型,第三个是注释内容,第四个是是否换行
        ts.addSyntheticLeadingComment(
          node,
          ts.SyntaxKind.MultiLineCommentTrivia,
          `* 自动生成的函数注释:${node.name?.getText() || '匿名函数'} *`,
          true
        );
      }
      // 继续遍历子节点
      return ts.visitEachChild(node, visitor, context);
    };
    return ts.visitNode(node, visitor);
  };
}

// 执行转换并生成输出代码
const result = ts.transform(sourceFile, [addFunctionCommentsTransformer]);
const transformedSourceFile = result.transformed[0];

// 将转换后的AST输出为JS代码
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const outputCode = printer.printFile(transformedSourceFile);

// 写入文件
fs.writeFileSync(outputFilePath, outputCode);

// 清理资源
result.dispose();

关键细节说明

  • 为什么不用直接修改statements?

    • TS的AST节点是只读设计的,直接赋值srcFile.statements = ...会绕过类型检查,可能导致后续遍历或打印时出错。
    • 这种方式只能处理顶层的函数声明,没法处理嵌套在if语句、类、其他函数内部的函数,覆盖范围有限。
  • Transformer API的优势

    • 官方提供的标准修改AST的方式,完全兼容TS的类型系统。
    • 递归遍历能覆盖所有层级的函数节点,不管是顶层还是嵌套的。
    • 用addSyntheticLeadingComment添加的注释会被正确解析并输出到最终的JS文件里。
  • 自定义注释内容
    你可以根据函数的元信息(比如参数、返回值)来生成更个性化的注释,比如:

    const paramNames = node.parameters.map(p => p.name.getText()).join(', ');
    ts.addSyntheticLeadingComment(
      node,
      ts.SyntaxKind.MultiLineCommentTrivia,
      `* 函数:${node.name?.getText() || '匿名函数'} *\n* 参数:${paramNames} *`,
      true
    );
    

内容的提问来源于stack exchange,提问作者Radu Szasz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:33:39