如何在 typescript-transformer 函数中正确转换 'this' 关键字?

How can I properly transform the 'this' keyword in a typescript-transformer function?

我创建了一个遍历 AST 并更改数组调用的打字稿转换器

myArr.push(el)Array.prototype.push.call(myArr, args)

除了数组在 class:

中使用 this 关键字的情况外,这适用于所有情况

this.myArr.push(el) 转换为 Array.prototype.push.call(this.myArr, args) 而正确的转换应该是: this.myArr.push(el)Array.prototype.push.call(_this.myArr, args)_this 已经由 ts-loader 插件创建)

我怎样才能做到这一点?

这是我的变压器的代码:

function getType(type) {
  if (type && type.symbol && type.symbol.name) {
    return type.symbol.name;
  } else if (
    type &&
    type.literalType &&
    type.literalType.symbol &&
    type.literalType.symbol.name
  ) {
    return type.literalType.symbol.name;
  }
  return null;
}
exports.__esModule = true;
const { ClassificationTypeNames } = require("typescript");
var ts = require("typescript");
var transformer = function (typechecker) {
  return function (context) {
    var visitor = function (node) {
      // 1. First check: chained expression
      // if it's array.filter().join().map() then I want to change only the first part
      // meaning 
      // if property access is a call expression - ignore and dont change
      if (
        ts.isCallExpression(node) &&
        ts.isPropertyAccessExpression(node.expression) &&
        ts.isCallExpression(node.expression.expression)

      ) {
        return ts.visitEachChild(node, visitor, context);
        
      }

      if (
        ts.isCallExpression(node) &&
        ts.isPropertyAccessExpression(node.expression)
      ) {
        const type = typechecker.getTypeAtLocation(node.expression.expression);
        const typeNameS = getType(type); 
        if (typeNameS === "Array") {
          const methodName = node.expression.name.getText();
          const callArgs = node.arguments;
          const identifier = node.expression.expression.getText();
          return ts.createCall(
            ts.createPropertyAccess(
              ts.createPropertyAccess(
                ts.createPropertyAccess(
                  ts.createIdentifier("Array"),
                  ts.createIdentifier("prototype")
                ),
                ts.createIdentifier(methodName)
              ),
              ts.createIdentifier("call")
            ),
            undefined,
            [ts.createIdentifier(identifier), ...callArgs]
          );
        }
      }

      return ts.visitEachChild(node, visitor, context);
    };
    return function (node) {
      return ts.visitNode(node, visitor);
    };
  };
};

发现错误。

我正在获取标识符并手动创建它。

const identifier = node.expression.expression.getText();

然后

ts.createIdentifier(identifier)

构造新节点的正确方法是将node.expression.expression直接传递给构造调用。

 return ts.createCall(
        ts.createPropertyAccess(
          ts.createPropertyAccess(
            ts.createPropertyAccess(
              ts.createIdentifier("Array"),
              ts.createIdentifier("prototype")
            ),
            ts.createIdentifier(methodName)
          ),
          ts.createIdentifier("call")
        ),
        undefined,
        [node.expression.expression, ...callArgs]
      );

这样 typescript 引擎就知道如何正确构建 _thisthis 引用。