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

如何在ts-morph中用getPreviousSibling获取目标节点而非语法点?

问题描述

使用ts-morph解析标识符定义时,处理fn.bind(this)这类代码时,找到bind标识符后调用getPreviousSibling()返回的是点号(.),而非预期的fn。需要一种更可靠的方式获取bind所属的左侧表达式(比如fn或this.fn中的主体部分),避免连续两次调用getPreviousSibling()。

解决方案

利用ts-morph的节点类型判断和内置方法实现,步骤如下:

  1. 获取bind标识符的父节点,它属于PropertyAccessExpression类型(对应x.y这种属性访问语法)。
  2. 调用父节点的getExpression()方法,直接获取属性访问左侧的表达式节点,这就是目标的fn(或this.fn中的this)。
  3. 若需提取最内层标识符,可对返回的表达式做类型判断后进一步处理。

修改后的示例代码:

import { Project, SyntaxKind, PropertyAccessExpression } from "ts-morph";

console.clear();

const project = new Project();

const file = project.createSourceFile(
  "foo.ts",
  `
  const fn = () => {}

  const fn2 = fn.bind(this);
  const fn3 = this.fn.bind(this);
`
);

const identifiers = file.getDescendantsOfKind(SyntaxKind.Identifier);
const bind = identifiers.find((i) => i.getText() === "bind");

if (bind) {
  // 获取父节点并断言为PropertyAccessExpression
  const propertyAccess = bind.getParent() as PropertyAccessExpression;
  // 获取左侧表达式
  const targetExpr = propertyAccess.getExpression();
  console.log({ targetExpr: targetExpr.getText() }); // 输出"fn"或"this.fn"
  
  // 提取最内层的标识符
  if (targetExpr.isKind(SyntaxKind.PropertyAccessExpression)) {
    console.log({ innerId: targetExpr.getNameNode().getText() }); // 输出"fn"
  } else if (targetExpr.isKind(SyntaxKind.Identifier)) {
    console.log({ id: targetExpr.getText() }); // 输出"fn"
  }
}
说明
  • PropertyAccessExpression是ts-morph对x.y这类语法的节点封装,getExpression()直接返回左侧的x部分,比手动遍历兄弟节点更可靠,面对嵌套属性访问(如a.b.c.bind())时,能直接拿到最外层的a.b.c。
  • 若需提取深层标识符,可递归或逐层判断节点类型,调用getNameNode()获取属性名标识符。

内容的提问来源于stack exchange,提问作者Jon Sud

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:05:15