如何让TypeScript AST工厂函数为节点设置父节点?
为TypeScript AST节点设置父节点的可行方案
TypeScript工厂函数创建AST节点时,确实不会自动为节点设置父节点,直接赋值node.parent会因该属性为只读而触发类型错误。以下是两种可行的解决方法:
方法一:通过类型断言绕过只读限制
parent属性在类型定义中标记为只读,但底层存储是可写的。可以用类型断言将节点转为any类型后直接赋值:
// 分步创建节点,方便单独设置父节点 const stateId = ts.factory.createIdentifier("state"); const propAccessExpr = ts.factory.createPropertyAccessExpression(stateId, "Foo"); // 绕过类型检查设置父节点 (stateId as any).parent = propAccessExpr; const testExpr = ts.factory.createBinaryExpression( propAccessExpr, ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createIdentifier("Bar") ); console.log( "Parent of state identifier:", ts.SyntaxKind[stateId.parent.kind] // 输出:PropertyAccessExpression );
方法二:递归遍历AST批量绑定父节点
如果需要为整个AST树的所有节点都设置父节点,可以编写一个递归遍历函数:
function bindASTParents(node: ts.Node, parentNode: ts.Node | null = null) { // 为当前节点设置父节点 (node as any).parent = parentNode; // 递归处理所有子节点 ts.forEachChild(node, childNode => bindASTParents(childNode, node)); } // 创建完整的AST节点 const testExpr = ts.factory.createBinaryExpression( ts.factory.createPropertyAccessExpression( ts.factory.createIdentifier("state"), "Foo" ), ts.factory.createToken(ts.SyntaxKind.EqualsToken), ts.factory.createIdentifier("Bar") ); // 为整个AST树绑定父节点 bindASTParents(testExpr); console.log( "Parent of state identifier:", ts.SyntaxKind[testExpr.left.expression.parent.kind] // 输出:PropertyAccessExpression );
注意事项
这两种方法都属于绕过TypeScript的类型检查机制,官方并未提供公开API来设置父节点——因为AST节点在TypeScript内部设计中默认是不可变的。如果后续对节点进行修改,可能会导致父节点引用失效,使用时需谨慎。
内容的提问来源于stack exchange,提问作者thedayturns
相关产品推荐
相关产品推荐

