如何用TypeScript Compiler API在AST树中查找特定SyntaxKind节点?
使用TypeScript Compiler API遍历AST查找特定类型节点
你之前的代码只获取了当前节点的直接子节点,没有递归遍历子节点的子节点,所以没法覆盖整棵AST树。要实现通用的findNodes函数,核心是要做深度优先的递归遍历,结合TypeScript提供的类型守卫函数(比如isReturnStatement、isClassDeclaration)筛选节点。
完整实现代码
import * as ts from "typescript"; /** * 递归遍历AST树,查找所有符合类型守卫条件的节点 * @param node 起始节点 * @param typeGuard 类型守卫函数,用于判断节点是否符合目标类型 * @returns 所有符合条件的节点数组 */ function findNodes<T extends ts.Node>(node: ts.Node, typeGuard: (node: ts.Node) => node is T): T[] { const result: T[] = []; // 先检查当前节点是否符合条件 if (typeGuard(node)) { result.push(node); } // 递归遍历所有子节点 ts.forEachChild(node, (child) => { result.push(...findNodes(child, typeGuard)); }); return result; } // 示例用法 // 假设你已经有了一个AST根节点(比如通过ts.createSourceFile解析得到的sourceFile) const sourceFile = ts.createSourceFile( "test.ts", ` class TestClass { method() { return 123; } } function foo() { return "hello"; } `, ts.ScriptTarget.Latest, true ); // 查找所有ReturnStatement节点 const returnStatements = findNodes(sourceFile, ts.isReturnStatement); console.log("找到的ReturnStatement数量:", returnStatements.length); // 输出2 // 查找所有ClassDeclaration节点 const classDeclarations = findNodes(sourceFile, ts.isClassDeclaration); console.log("找到的ClassDeclaration数量:", classDeclarations.length); // 输出1
关键说明
ts.forEachChild会遍历当前节点的所有直接子节点,但不会自动递归,所以我们需要在遍历子节点时再次调用findNodes,实现深度遍历。- TypeScript提供的
isXXX函数(比如ts.isReturnStatement)是类型守卫,不仅能判断节点类型,还能让TypeScript推断出返回数组的具体类型,保证类型安全。 - 这个函数是通用的,只要传入对应的类型守卫函数,就能查找任意类型的AST节点。
内容的提问来源于stack exchange,提问作者Ced
相关产品推荐
相关产品推荐

