# ast-types 中文文档

规范地址：https://npmcn.com/package/ast-types/

版本：0\.16\.3
npm 元数据更新时间：2026-08-30T20:40:15.303Z
中文译文更新时间：2026-11-05T15:48:58.441Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/ast-types
原文对照：https://npmcn.com/package/ast-types/?lang=original
项目主页：https://github.com/benjamn/ast-types
源码仓库：https://github.com/benjamn/ast-types

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：682 kB，105 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=4
- 运行依赖：1 个
- 首次发布：2013-04-24T17:48:55.314Z
- 最新版本发布：2026-08-30T20:40:14.973Z
- 近 30 天下载量：282741975（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：175（近 12 个月 3 个）

## 中文简介

Esprima与执行Mozilla JS Parser API相容

## 安装

```sh
npm install ast-types
```

也可以使用：`pnpm add ast-types`、`yarn add ast-types`、`bun add ast-types`

## README

# AST 类型 [![CI](https://github.com/benjamn/ast-types/actions/workflows/main.yml/badge.svg)](https://github.com/benjamn/ast-types/actions/workflows/main.yml) [![npm](https://img.shields.io/npm/v/ast-types.svg)](https://www.npmjs.com/package/ast-types)

本单元提供高效、模块化、, [埃斯皮里亚](https://github.com/ariya/esprima)\- 执行不兼容 页:1 [抽象语法 树](http://en.wikipedia.org/wiki/Abstract_syntax_tree) 类型等级 创始人: [莫齐拉·帕塞尔 API 密码](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API)。 。 。 .

## 安装

```
npm install ast-types
```

货包本身的TypeScript申报;没有 `@types/ast-types` 要安装。 TypeScript 4.4 及以后的支持,以及 对申报的每份申报都按4.4、4.9和5.x分类.

继续工作 `ast-types` 本身:

```
git clone https://github.com/benjamn/ast-types.git
cd ast-types
npm install
npm test
```

## 基本用途

```js
import assert from "assert";
import {
  namedTypes as n,
  builders as b,
} from "ast-types";

var fooId = b.identifier("foo");
var ifFoo = b.ifStatement(fooId, b.blockStatement([
  b.expressionStatement(b.callExpression(fooId, []))
]));

assert.ok(n.IfStatement.check(ifFoo));
assert.ok(n.Statement.check(ifFoo));
assert.ok(n.Node.check(ifFoo));

assert.ok(n.BlockStatement.check(ifFoo.consequent));
assert.strictEqual(
  ifFoo.consequent.body[0].expression.arguments.length,
  0,
);

assert.strictEqual(ifFoo.test, fooId);
assert.ok(n.Expression.check(ifFoo.test));
assert.ok(n.Identifier.check(ifFoo.test));
assert.ok(!n.Statement.check(ifFoo.test));
```

## 类型脚本

所发表的宣言来自与《公约》相同的定义 运行时间类型, 因此每个节点类型都可以作为类型Script类型 同名词下 `namedTypes`,以及 `NodePath` 财务报告和审定财务报表 `Type` 通用 :

```ts
import {
  builders as b,
  namedTypes as n,
  visit,
  NodePath,
} from "ast-types";

const fooId: n.Identifier = b.identifier("foo");
const call: n.CallExpression = b.callExpression(fooId, []);

// Visitor methods receive a NodePath parameterized by the node type, so
// path.node is narrowed for you.
visit(call, {
  visitCallExpression(path) {
    const callee: n.CallExpression["callee"] = path.node.callee;
    this.traverse(path);
  },
});

declare const somePath: NodePath<n.CallExpression>;
somePath.node.arguments;
```

注意节点类型中的 TypeScript 类型描述定义 接受,这往往是一个工会。 拓宽一个字段以承认一个节点形状 消费者可能需要缩小范围 [变动情况](https://npmcn.com/package/ast-types/CHANGELOG.md) 对于那些已经发生的.

## AST 倾斜

因为它如此透彻地理解了AST类型系统,这个库 能够提供极佳的节点迭接和倒转机制.

如果你想要完全控制 转弯,你只需要一个方法 列出您 AST 节点的已知字段并获取其 价值,你可能会对原始人感兴趣 `getFieldNames` 财务报告和审定财务报表 `getFieldValue`数字 :

```js
import {
  getFieldNames,
  getFieldValue,
} from "ast-types";

const partialFunExpr = { type: "FunctionExpression" };

// Even though partialFunExpr doesn't actually contain all the fields that
// are expected for a FunctionExpression, types.getFieldNames knows:
console.log(getFieldNames(partialFunExpr));
// [ 'type', 'id', 'params', 'body', 'generator', 'expression',
//   'defaults', 'rest', 'async' ]

// For fields that have default values, types.getFieldValue will return
// the default if the field is not actually defined.
console.log(getFieldValue(partialFunExpr, "generator"));
// false
```

两个低级的助手功能, `eachField` 财务报告和审定财务报表 `someField`,为 定义 `getFieldNames` 财务报告和审定财务报表 `getFieldValue`数字 :

```js
// Iterate over all defined fields of an object, including those missing
// or undefined, passing each field name and effective value (as returned
// by getFieldValue) to the callback. If the object has no corresponding
// Def, the callback will never be called.
export function eachField(object, callback, context) {
  getFieldNames(object).forEach(function(name) {
    callback.call(this, name, getFieldValue(object, name));
  }, context);
}

// Similar to eachField, except that iteration stops as soon as the
// callback returns a truthy value. Like Array.prototype.some, the final
// result is either true or false to indicates whether the callback
// returned true for any element or not.
export function someField(object, callback, context) {
  return getFieldNames(object).some(function(name) {
    return callback.call(this, name, getFieldValue(object, name));
  }, context);
}
```

这就是你如何复制一个AST节点:

```js
import { eachField } from "ast-types";
const copy = {};
eachField(node, function(name, value) {
  // Note that undefined fields will be visited too, according to
  // the rules associated with node.type, and default field values
  // will be substituted if appropriate.
  copy[name] = value;
})
```

但还不止这些! 您也可以轻松访问整个语法树 强者 `types.visit` 抽象化.

举个小例子来说明.. `arguments.callee` 从未在 `ast`数字 :

```js
import assert from "assert";
import {
  visit,
  namedTypes as n,
} from "ast-types";

visit(ast, {
  // This method will be called for any node with .type "MemberExpression":
  visitMemberExpression(path) {
    // Visitor methods receive a single argument, a NodePath object
    // wrapping the node of interest.
    var node = path.node;

    if (
      n.Identifier.check(node.object) &&
      node.object.name === "arguments" &&
      n.Identifier.check(node.property)
    ) {
      assert.notStrictEqual(node.property.name, "callee");
    }

    // It's your responsibility to call this.traverse with some
    // NodePath object (usually the one passed into the visitor
    // method) before the visitor method returns, or return false to
    // indicate that the traversal need not continue any further down
    // this subtree.
    this.traverse(path);
  }
});
```

这里有一个 稍多参与的例子 改造 `...rest` 参数进入浏览器运行的 ES5 JavaScript :

```js
import assert from "assert";
import {
  builders as b,
  namedTypes as n,
  visit,
} from "ast-types";

// Reuse the same AST structure for Array.prototype.slice.call.
var sliceExpr = b.memberExpression(
  b.memberExpression(
    b.memberExpression(
      b.identifier("Array"),
      b.identifier("prototype"),
      false
    ),
    b.identifier("slice"),
    false
  ),
  b.identifier("call"),
  false
);

visit(ast, {
  // This method will be called for any node whose type is a subtype of
  // Function (e.g., FunctionDeclaration, FunctionExpression, and
  // ArrowFunctionExpression). Note that types.visit precomputes a
  // lookup table from every known type to the appropriate visitor
  // method to call for nodes of that type, so the dispatch takes
  // constant time.
  visitFunction(path) {
    // Visitor methods receive a single argument, a NodePath object
    // wrapping the node of interest.
    const node = path.node;

    // It's your responsibility to call this.traverse with some
    // NodePath object (usually the one passed into the visitor
    // method) before the visitor method returns, or return false to
    // indicate that the traversal need not continue any further down
    // this subtree. An assertion will fail if you forget, which is
    // awesome, because it means you will never again make the
    // disastrous mistake of forgetting to traverse a subtree. Also
    // cool: because you can call this method at any point in the
    // visitor method, it's up to you whether your traversal is
    // pre-order, post-order, or both!
    this.traverse(path);

    // This traversal is only concerned with Function nodes that have
    // rest parameters.
    if (!node.rest) {
      return;
    }

    // For the purposes of this example, we won't worry about functions
    // with Expression bodies.
    n.BlockStatement.assert(node.body);

    // Use types.builders to build a variable declaration of the form
    //
    //   var rest = Array.prototype.slice.call(arguments, n);
    //
    // where `rest` is the name of the rest parameter, and `n` is a
    // numeric literal specifying the number of named parameters the
    // function takes.
    const restVarDecl = b.variableDeclaration("var", [
      b.variableDeclarator(
        node.rest,
        b.callExpression(sliceExpr, [
          b.identifier("arguments"),
          b.literal(node.params.length)
        ])
      )
    ]);

    // Similar to doing node.body.body.unshift(restVarDecl), except
    // that the other NodePath objects wrapping body statements will
    // have their indexes updated to accommodate the new statement.
    path.get("body", "body").unshift(restVarDecl);

    // Nullify node.rest now that we have simulated the behavior of
    // the rest parameter using ordinary JavaScript.
    path.get("rest").replace(null);

    // There's nothing wrong with doing node.rest = null, but I wanted
    // to point out that the above statement has the same effect.
    assert.strictEqual(node.rest, null);
  }
});
```

这是你可能使用 `types.visit` 用于执行一个函数 确定给定函数节点是否指的是 `this`数字 :

```js
function usesThis(funcNode) {
  n.Function.assert(funcNode);
  var result = false;

  visit(funcNode, {
    visitThisExpression(path) {
      result = true;

      // The quickest way to terminate the traversal is to call
      // this.abort(), which throws a special exception (instanceof
      // this.AbortRequest) that will be caught in the top-level
      // types.visit method, so you don't have to worry about
      // catching the exception yourself.
      this.abort();
    },

    visitFunction(path) {
      // ThisExpression nodes in nested scopes don't count as `this`
      // references for the original function node, so we can safely
      // avoid traversing this subtree.
      return false;
    },

    visitCallExpression(path) {
      const node = path.node;

      // If the function contains CallExpression nodes involving
      // super, those expressions will implicitly depend on the
      // value of `this`, even though they do not explicitly contain
      // any ThisExpression nodes.
      if (this.isSuperCallExpression(node)) {
        result = true;
        this.abort(); // Throws AbortRequest exception.
      }

      this.traverse(path);
    },

    // Yes, you can define arbitrary helper methods.
    isSuperCallExpression(callExpr) {
      n.CallExpression.assert(callExpr);
      return this.isSuperIdentifier(callExpr.callee)
          || this.isSuperMemberExpression(callExpr.callee);
    },

    // And even helper helper methods!
    isSuperIdentifier(node) {
      return n.Identifier.check(node.callee)
          && node.callee.name === "super";
    },

    isSuperMemberExpression(node) {
      return n.MemberExpression.check(node.callee)
          && n.Identifier.check(node.callee.object)
          && node.callee.object.name === "super";
    }
  });

  return result;
}
```

你可能猜到,当一个 `AbortRequest` 是从树下抛出 例外将从相应的呼叫中传播到 `this.traverse` 在祖先的访客方法。 如果你决定取消 请求,只需抓住例外,并调用它 `.cancel()` 方法。 这个 其余树在树下 `try`\- 说吧`catch` 块将废弃,但 祖先节点的其余兄弟姐妹将仍然被访问.

## 节点Path

这个 `NodePath` 对象传递给访问者的方法是 AST 周围的包装器 节点,它可以提供对祖先物体链的连接 (一路回AST根)和范围信息.

总的来说, `path.node` 是指被包裹的节点, `path.parent.node` 指最近一个 `Node` 祖师相传, `path.parent.parent.node` 页:1 外祖相等相传.

请注意: `path.node` 可能不是 `path.parent.node`例如,情况可能是: `path.node` 实值 属于父节点直接子的数组元素:

```js
path.node === path.parent.node.elements[3]
```

在这种情况下,你应该知道 `path.parentPath` 提供 更精细地访问对象的完整路径(不只是 `Node` (一) 从AST的根部:

```js
// In reality, path.parent is the grandparent of path:
path.parentPath.parentPath === path.parent

// The path.parentPath object wraps the elements array (note that we use
// .value because the elements array is not a Node):
path.parentPath.value === path.parent.node.elements

// The path.node object is the fourth element in that array:
path.parentPath.value[3] === path.node

// Unlike path.node and path.value, which are synonyms because path.node
// is a Node object, path.parentPath.node is distinct from
// path.parentPath.value, because the elements array is not a
// Node. Instead, path.parentPath.node refers to the closest ancestor
// Node, which happens to be the same as path.parent.node:
path.parentPath.node === path.parent.node

// The path is named for its index in the elements array:
path.name === 3

// Likewise, path.parentPath is named for the property by which
// path.parent.node refers to it:
path.parentPath.name === "elements"

// Putting it all together, we can follow the chain of object references
// from path.parent.node all the way to path.node by accessing each
// property by name:
path.parent.node[path.parentPath.name][path.name] === path.node
```

这些 `NodePath` 对象是在无 修改 AST 节点本身, 因此如果相同的节点没有问题 多次出现在 AST 中( 如 `Array.prototype.slice.call` 内 因为它将用微调访问 `NodePath` 每次出现的时候.

儿童 `NodePath` 通过调用 `.get` 方法 父母关系 `NodePath` 对象 :

```js
// If a NodePath object for the elements array has never been created
// before, it will be created here and cached in the future:
path.get("elements").get(3).value === path.value.elements[3]

// Alternatively, you can pass multiple property names to .get instead of
// chaining multiple .get calls:
path.get("elements", 0).value === path.value.elements[0]
```

`NodePath` 对象支持一些有用的方法:

```js
// Replace one node with another node:
var fifth = path.get("elements", 4);
fifth.replace(newNode);

// Now do some stuff that might rearrange the list, and this replacement
// remains safe:
fifth.replace(newerNode);

// Replace the third element in an array with two new nodes:
path.get("elements", 2).replace(
  b.identifier("foo"),
  b.thisExpression()
);

// Remove a node and its parent if it would leave a redundant AST node:
//e.g. var t = 1, y =2; removing the `t` and `y` declarators results in `var undefined`.
path.prune(); //returns the closest parent `NodePath`.

// Remove a node from a list of nodes:
path.get("elements", 3).replace();

// Add three new nodes to the beginning of a list of nodes:
path.get("elements").unshift(a, b, c);

// Remove and return the first node in a list of nodes:
path.get("elements").shift();

// Push two new nodes onto the end of a list of nodes:
path.get("elements").push(d, e);

// Remove and return the last node in a list of nodes:
path.get("elements").pop();

// Insert a new node before/after the seventh node in a list of nodes:
var seventh = path.get("elements", 6);
seventh.insertBefore(newNode);
seventh.insertAfter(newNode);

// Insert a new element at index 5 in a list of nodes:
path.get("elements").insertAt(5, newNode);
```

## 范围

显示为 `path.scope` 在AST轨道提供时 关于可变和功能声明的信息 包含 `path.node`。见 [范围.ts](https://npmcn.com/package/ast-types/src/scope.ts) 为公众服务 接口,目前包括 `.isGlobal`, (中文(简体) ), `.getGlobalScope()`, (中文(简体) ), `.depth`, (中文(简体) ), `.declares(name)`, (中文(简体) ), `.lookup(name)`,以及 `.getBindings()`。 。 。 .

## 自定义 AST 节点类型

这个 `ast-types` 模块设计要扩展。 为此 为指定新的AST节点类型提供可读、可声明的语法, 主要基于 `require("ast-types").Type.def` 函数 :

```js
import {
  Type,
  builtInTypes,
  builders as b,
  finalize,
} from "ast-types";

const { def } = Type;
const { string } = builtInTypes;

// Suppose you need a named File type to wrap your Programs.
def("File")
  .bases("Node")
  .build("name", "program")
  .field("name", string)
  .field("program", def("Program"));

// Prevent further modifications to the File type (and any other
// types newly introduced by def(...)).
finalize();

// The b.file builder function is now available. It expects two
// arguments, as named by .build("name", "program") above.
const main = b.file("main.js", b.program([
  // Pointless program contents included for extra color.
  b.functionDeclaration(b.identifier("succ"), [
    b.identifier("x")
  ], b.blockStatement([
    b.returnStatement(
      b.binaryExpression(
        "+", b.identifier("x"), b.literal(1)
      )
    )
  ]))
]));

assert.strictEqual(main.name, "main.js");
assert.strictEqual(main.program.body[0].params[0].name, "x");
// etc.

// If you pass the wrong type of arguments, or fail to pass enough
// arguments, an AssertionError will be thrown.

b.file(b.blockStatement([]));
// ==> AssertionError: {"body":[],"type":"BlockStatement","loc":null} does not match type string

b.file("lib/types.js", b.thisExpression());
// ==> AssertionError: {"type":"ThisExpression","loc":null} does not match type Program
```

这个 `def` 语法用于定义所有默认 AST 节点类型 [bayl-core.ts (英语)](https://npmcn.com/package/ast-types/src/def/babel-core.ts), (中文(简体) ), [贝贝.ts](https://npmcn.com/package/ast-types/src/def/babel.ts), (中文(简体) ), [核心数.t](https://npmcn.com/package/ast-types/src/def/core.ts), (中文(简体) ), [提议](https://npmcn.com/package/ast-types/src/def/es-proposals.ts), (中文(简体) ), [es6. 吨级](https://npmcn.com/package/ast-types/src/def/es6.ts), (中文(简体) ), [es2016.ts (英语)](https://npmcn.com/package/ast-types/src/def/es2016.ts), (中文(简体) ), [es2017.ts (英语)](https://npmcn.com/package/ast-types/src/def/es2017.ts), (中文(简体) ), [2018.ts (英语)](https://npmcn.com/package/ast-types/src/def/es2018.ts), (中文(简体) ), [es2019.ts (英语)](https://npmcn.com/package/ast-types/src/def/es2019.ts), (中文(简体) ), [es2020.ts (英语)](https://npmcn.com/package/ast-types/src/def/es2020.ts), (中文(简体) ), [es2021.ts (英语)](https://npmcn.com/package/ast-types/src/def/es2021.ts), (中文(简体) ), [es2022.ts (英语)](https://npmcn.com/package/ast-types/src/def/es2022.ts), (中文(简体) ), [双子宫](https://npmcn.com/package/ast-types/src/def/esprima.ts), (中文(简体) ), [流量.ts](https://npmcn.com/package/ast-types/src/def/flow.ts), (中文(简体) ), [页:1](https://npmcn.com/package/ast-types/src/def/jsx.ts), (中文(简体) ), [类型注释.ts](https://npmcn.com/package/ast-types/src/def/type-annotations.ts), (中文(简体) ), 财务报告和审定财务报表 [类型标记.ts](https://npmcn.com/package/ast-types/src/def/typescript.ts), (中文(简体) ), 所以,你已经 并不缺乏可以学习的例子.

## 常见问题

### ast-types 是什么？

Esprima与执行Mozilla JS Parser API相容

### 如何安装 ast-types？

在项目目录运行 npm install ast-types，或使用 pnpm add / yarn add / bun add。

### ast-types 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### ast-types 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### ast-types 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=4。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### ast-types 可以商用吗？

ast-types 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### ast-types 的下载量有多少？

根据 npm 官方下载统计，ast-types 在 2026/10/05 – 2026/11/03 这 30 天内被下载 282,741,975 次，日均约 9,424,733 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### ast-types 还在维护吗？

最新版本 0\.16\.3 发布于 2026/08/31（2 个月前）；至今共发布 175 个版本，其中过去 12 个月发布了 3 个；首次发布于 2013/04/25。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

