> ## Content Index
> Fetch the complete content index at: https://blog.vercanti.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Babel TypeScript 类型完全参考
- URL: https://blog.vercanti.com/babel-typescript-lei-xing-wan-quan-can-kao/
- Published: 2026-08-28T14:34:54.000Z
- Updated: 2026-08-28T14:57:38.000Z
- Description: 本文档专门面向 TypeScript 使用者，覆盖 Babel 工具链所有包的完整类型定义，重点解决"对象很多、没有类型提示很费心神"的问题。 配合 技巧步骤/Babel AST入门 阅读，后者侧重基本用法和实战示例，本文侧重 TypeScript 类型系统。 1. 安装与 TypeScript 配置(#%E5%AE%89%E8%A3%85%E4%B8%8E-typescript-%E9%85%8D%E7%BD%AE) 2. @babel/parser 类型详解(#babelparser-%E7%B1%BB%E5%9E%8B%E8%AF%A6%E8%A7
- Author: yellowdog
- Tags: js逆向, AST

> 官方文档：<https://babeljs.io/docs/babel-types>  
> 适用版本：@babel/types 7.x+（2026-05-08 核实）

本文档专门面向 TypeScript 使用者，覆盖 Babel 工具链所有包的完整类型定义，重点解决"对象很多、没有类型提示很费心神"的问题。

配合 技巧步骤/Babel AST入门 阅读，后者侧重基本用法和实战示例，本文侧重 TypeScript 类型系统。

---

## 目录

1. [安装与 TypeScript 配置](#%E5%AE%89%E8%A3%85%E4%B8%8E-typescript-%E9%85%8D%E7%BD%AE)
2. [@babel/parser 类型详解](#babelparser-%E7%B1%BB%E5%9E%8B%E8%AF%A6%E8%A7%A3)
3. [@babel/types 节点类型详解](#babeltypes-%E8%8A%82%E7%82%B9%E7%B1%BB%E5%9E%8B%E8%AF%A6%E8%A7%A3)
4. [@babel/traverse 类型详解](#babeltraverse-%E7%B1%BB%E5%9E%8B%E8%AF%A6%E8%A7%A3)
5. [@babel/generator 类型详解](#babelgenerator-%E7%B1%BB%E5%9E%8B%E8%AF%A6%E8%A7%A3)
6. [@babel/core 类型详解](#babelcore-%E7%B1%BB%E5%9E%8B%E8%AF%A6%E8%A7%A3)
7. [TypeScript 使用模式](#typescript-%E4%BD%BF%E7%94%A8%E6%A8%A1%E5%BC%8F)

---

## 安装与 TypeScript 配置

### 安装命令

```bash
# 运行时依赖
npm install @babel/parser @babel/traverse @babel/types @babel/generator @babel/core

# TypeScript 类型声明
# @babel/parser、@babel/types、@babel/core 自带类型，无需单独安装
npm install --save-dev @types/babel__traverse @types/babel__generator

```

### 各包类型来源汇总

| 包                | 类型声明位置          | 说明                                                    |
| ---------------- | --------------- | ----------------------------------------------------- |
| @babel/parser    | 包内自带            | node\_modules/@babel/parser/typings/babel-parser.d.ts |
| @babel/types     | 包内自带            | 自动生成，最完整                                              |
| @babel/core      | 包内自带            | node\_modules/@babel/core/lib/index.d.ts              |
| @babel/traverse  | DefinitelyTyped | @types/babel\_\_traverse                              |
| @babel/generator | DefinitelyTyped | @types/babel\_\_generator                             |

### tsconfig.json 推荐配置

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "skipLibCheck": false
  }
}

```

`esModuleInterop: true` 是关键，因为 `@babel/traverse` 和 `@babel/generator` 用 `export default` 导出，但实际是 CommonJS 模块，没有这个选项 `import traverse from` 会报错。

### 推荐的 import 方式

```typescript
// @babel/parser —— 具名导入
import { parse, parseExpression } from "@babel/parser";

// @babel/types —— 命名空间导入（对象很多，用 * as t 最方便）
import * as t from "@babel/types";

// @babel/traverse —— 默认导入（需要 esModuleInterop）
import traverse from "@babel/traverse";

// @babel/generator —— 默认导入
import generate from "@babel/generator";

// @babel/core —— 具名导入
import { transformSync, parseSync } from "@babel/core";

```

---

## @babel/parser 类型详解

### 函数签名

```typescript
import { parse, parseExpression } from "@babel/parser";

// 解析完整程序，返回 File 节点（根节点）
function parse(code: string, options?: ParserOptions): t.File;

// 解析单个表达式，返回 Expression 节点
function parseExpression(code: string, options?: ParserOptions): t.Expression;

```

### ParserOptions 接口（完整字段）

```typescript
interface ParserOptions {
  // ---- 语法模式 ----

  // 模块类型
  // "script"      : 默认，普通脚本，不支持 import/export
  // "module"      : ES 模块，支持 import/export
  // "commonjs"    : CommonJS（允许顶层 return、new.target、资源声明）
  // "unambiguous" : 自动检测（有 import/export 则为 module，否则为 script）
  sourceType?: "script" | "commonjs" | "module" | "unambiguous";

  // 强制严格模式（默认 false）
  strictMode?: boolean;

  // 启用语法插件（见下方插件列表）
  plugins?: ParserPlugin[];

  // ---- 容错与恢复 ----

  // 遇到语法错误时继续解析，而非抛出异常（处理混淆代码时建议开启）
  errorRecovery?: boolean;

  // ---- 位置信息 ----

  // 源文件名，会附加到位置信息中
  sourceFilename?: string;

  // 起始行号（默认 1）
  startLine?: number;

  // 起始列号（默认 0）
  startColumn?: number;

  // 起始字符索引（默认 0）
  startIndex?: number;

  // 每个节点附加 [start, end] 位置数组（默认 false）
  ranges?: boolean;

  // ---- 节点控制 ----

  // 把 token 列表附加到 AST 的 tokens 字段（默认 false）
  tokens?: boolean;

  // 是否将注释挂载到相邻节点（默认 true）
  attachComment?: boolean;

  // 把 (expr) 括号表达式包装成 ParenthesizedExpression 节点（默认 false）
  createParenthesizedExpressions?: boolean;

  // 把 import() 解析为 ImportExpression 而非 CallExpression（默认 true）
  createImportExpressions?: boolean;

  // ---- 特殊权限 ----

  // 允许在任意位置使用 import/export（默认 false）
  allowImportExportEverywhere?: boolean;

  // 允许在函数外使用 await（默认 false）
  allowAwaitOutsideFunction?: boolean;

  // 允许在函数外使用 yield（默认 false）
  allowYieldOutsideFunction?: boolean;

  // 允许在函数外使用 new.target（默认 false）
  allowNewTargetOutsideFunction?: boolean;

  // 允许在函数外使用 return（默认 false）
  allowReturnOutsideFunction?: boolean;

  // 允许在非方法中使用 super（默认 false）
  allowSuperOutsideMethod?: boolean;

  // 允许未声明的 export（默认 false）
  allowUndeclaredExports?: boolean;

  // 是否遵循 Annex B（传统 JS 兼容性规则，默认 true）
  annexB?: boolean;
}

```

### plugins 可选值

`plugins` 字段接受 `ParserPlugin[]`，每个元素可以是字符串，也可以是 `[插件名, 选项对象]` 的元组。

```typescript
type ParserPlugin =
  // 语言扩展
  | "flow"
  | "flowComments"
  | "jsx"
  | "typescript"
  | "v8intrinsic"

  // 实验性 ECMAScript 提案
  | "asyncDoExpressions"
  | "decimal"
  | "decorators"                    // 需要配合选项：["decorators", { version: "2023-11", decoratorsBeforeExport: true }]
  | "decorators-legacy"
  | "decoratorAutoAccessors"
  | "deferredImportEvaluation"
  | "deprecatedImportAssert"
  | "destructuringPrivate"
  | "discardBinding"
  | "doExpressions"
  | "explicitResourceManagement"    // using / await using
  | "exportDefaultFrom"
  | "functionBind"
  | "functionSent"
  | "importReflection"
  | "moduleBlocks"
  | "optionalChainingAssign"
  | "partialApplication"
  | "pipelineOperator"              // 需要配合选项：["pipelineOperator", { proposal: "minimal" }]
  | "recordAndTuple"
  | "sourcePhaseImports"
  | "throwExpressions"

  // ESTree 兼容输出（供 ESLint 使用）
  | "estree"

  // 以下默认已启用
  | "asyncGenerators"
  | "bigInt"
  | "classProperties"
  | "classPrivateProperties"
  | "classPrivateMethods"
  | "classStaticBlock"
  | "dynamicImport"
  | "exportNamespaceFrom"
  | "logicalAssignment"
  | "nullishCoalescingOperator"
  | "numericSeparator"
  | "objectRestSpread"
  | "optionalCatchBinding"
  | "optionalChaining"
  | "privateIn"
  | "regexpUnicodeSets"
  | "topLevelAwait"
  | "importAttributes";

```

### 带类型的常用示例

```typescript
import { parse, parseExpression } from "@babel/parser";
import * as t from "@babel/types";

// 返回类型明确为 t.File
const ast: t.File = parse(`const x = 1`, {
  sourceType: "module",
  plugins: ["typescript"],
  errorRecovery: true,
});

// Program 是 ast.program，包含所有顶层语句
const program: t.Program = ast.program;

// parseExpression 返回 t.Expression（联合类型，需要收窄）
const expr: t.Expression = parseExpression(`a + b`);
if (t.isBinaryExpression(expr)) {
  // 这里 expr 被收窄为 t.BinaryExpression
  console.log(expr.operator); // string，类型安全
}

```

---

## @babel/types 节点类型详解

### BaseNode 基础接口

所有 AST 节点都继承 `BaseNode`：

```typescript
interface BaseNode {
  type: string;
  start?: number | null;      // 起始字符偏移
  end?: number | null;        // 结束字符偏移
  loc?: SourceLocation | null; // 行列位置信息
  leadingComments?: Comment[];
  innerComments?: Comment[];
  trailingComments?: Comment[];
  extra?: Record<string, unknown> | null;
}

interface SourceLocation {
  start: Position;
  end: Position;
  filename: string;
  identifierName?: string | null;
}

interface Position {
  line: number;   // 1-based
  column: number; // 0-based
  index: number;  // 字符偏移，0-based
}

```

### 核心节点 TypeScript 接口定义

#### 顶层节点

```typescript
interface File extends BaseNode {
  type: "File";
  program: Program;
  comments?: (CommentBlock | CommentLine)[] | null;
  tokens?: any[] | null;
}

interface Program extends BaseNode {
  type: "Program";
  body: Statement[];
  directives: Directive[];            // "use strict" 等指令
  sourceType: "script" | "module";
  interpreter?: InterpreterDirective | null; // #!/usr/bin/env node
}

```

#### 标识符与字面量

```typescript
interface Identifier extends BaseNode {
  type: "Identifier";
  name: string;
  // 以下字段在 TypeScript/Flow 语法中出现
  optional?: boolean | null;
  typeAnnotation?: TypeAnnotation | TSTypeAnnotation | null;
  decorators?: Decorator[] | null;
}

interface StringLiteral extends BaseNode {
  type: "StringLiteral";
  value: string;
}

interface NumericLiteral extends BaseNode {
  type: "NumericLiteral";
  value: number;
}

interface BooleanLiteral extends BaseNode {
  type: "BooleanLiteral";
  value: boolean;
}

interface NullLiteral extends BaseNode {
  type: "NullLiteral";
}

interface BigIntLiteral extends BaseNode {
  type: "BigIntLiteral";
  value: string; // 注意：是字符串，不是 bigint
}

interface RegExpLiteral extends BaseNode {
  type: "RegExpLiteral";
  pattern: string;
  flags: string;
}

// 模板字符串：`hello ${name}`
interface TemplateLiteral extends BaseNode {
  type: "TemplateLiteral";
  quasis: TemplateElement[];       // 静态文本片段（n+1 个）
  expressions: (Expression | TSType)[]; // 动态插值（n 个）
}

// 模板字符串的静态片段
interface TemplateElement extends BaseNode {
  type: "TemplateElement";
  value: {
    raw: string;    // 原始文本（含转义符，如 \n）
    cooked: string | null; // 解析后文本（null 表示含非法转义）
  };
  tail: boolean; // 是否是最后一个片段
}

```

#### 表达式节点

```typescript
// obj.prop（computed=false）或 obj[expr]（computed=true）
// 注意：MemberExpression 是联合类型
type MemberExpression = MemberExpressionComputed | MemberExpressionNonComputed;

interface MemberExpressionNonComputed extends BaseNode {
  type: "MemberExpression";
  object: Expression | Super;
  property: Identifier | PrivateName;
  computed: false;
  optional?: boolean | null;
}

interface MemberExpressionComputed extends BaseNode {
  type: "MemberExpression";
  object: Expression | Super;
  property: Expression;
  computed: true;
  optional?: boolean | null;
}

// fn(a, b)
interface CallExpression extends BaseNode {
  type: "CallExpression";
  callee: Expression | Super | V8IntrinsicIdentifier;
  arguments: (Expression | SpreadElement | ArgumentPlaceholder)[];
  optional?: boolean | null;
  typeArguments?: TypeParameterInstantiation | TSTypeParameterInstantiation | null;
}

// a + b, a === b, a in b 等
interface BinaryExpression extends BaseNode {
  type: "BinaryExpression";
  operator:
    | "+" | "-" | "/" | "%" | "*" | "**"
    | "&" | "|" | ">>" | ">>>" | "<<" | "^"
    | "==" | "===" | "!=" | "!=="
    | "in" | "instanceof"
    | ">" | "<" | ">=" | "<="
    | "|>";
  left: Expression | PrivateName;
  right: Expression;
}

// x = 1, a += b 等
interface AssignmentExpression extends BaseNode {
  type: "AssignmentExpression";
  operator:
    | "=" | "+=" | "-=" | "/=" | "%=" | "*=" | "**="
    | "&=" | "|=" | ">>=" | ">>>=" | "<<=" | "^="
    | "||=" | "&&=" | "??=";
  left:
    | Identifier | MemberExpression | OptionalMemberExpression
    | ArrayPattern | ObjectPattern
    | TSAsExpression | TSSatisfiesExpression | TSTypeAssertion | TSNonNullExpression;
  right: Expression;
}

// { a: 1, b: 2 }
interface ObjectExpression extends BaseNode {
  type: "ObjectExpression";
  properties: (ObjectMethod | ObjectProperty | SpreadElement)[];
}

// 对象属性（也是联合类型）
type ObjectProperty = ObjectPropertyComputed | ObjectPropertyNonComputed;

interface ObjectPropertyNonComputed extends BaseNode {
  type: "ObjectProperty";
  key: Identifier | StringLiteral | NumericLiteral | BigIntLiteral | PrivateName;
  value: Expression | PatternLike;
  computed: false;
  shorthand: boolean;   // 是否是简写形式：{ a } 而非 { a: a }
  decorators?: Decorator[] | null;
}

interface ObjectPropertyComputed extends BaseNode {
  type: "ObjectProperty";
  key: Expression;
  value: Expression | PatternLike;
  computed: true;
  shorthand: boolean;
  decorators?: Decorator[] | null;
}

// [1, 2, 3]
interface ArrayExpression extends BaseNode {
  type: "ArrayExpression";
  elements: (null | Expression | SpreadElement)[]; // null 表示空位：[1,,3]
}

```

#### 函数节点

```typescript
// function foo(a, b) { ... }
interface FunctionDeclaration extends BaseNode {
  type: "FunctionDeclaration";
  id: Identifier | null;        // 匿名函数声明时为 null（export default function）
  params: FunctionParameter[];
  body: BlockStatement;
  generator: boolean;           // function*
  async: boolean;               // async function
  declare?: boolean | null;     // TypeScript: declare function
  returnType?: TypeAnnotation | TSTypeAnnotation | null;
  typeParameters?: TypeParameterDeclaration | TSTypeParameterDeclaration | null;
  predicate?: FlowPredicate | null;
}

// const fn = function(a, b) { ... }
interface FunctionExpression extends BaseNode {
  type: "FunctionExpression";
  id?: Identifier | null;       // 具名函数表达式：const fn = function foo() {}
  params: FunctionParameter[];
  body: BlockStatement;
  generator: boolean;
  async: boolean;
  returnType?: TypeAnnotation | TSTypeAnnotation | null;
  typeParameters?: TypeParameterDeclaration | TSTypeParameterDeclaration | null;
  predicate?: FlowPredicate | null;
}

// (a, b) => a + b  或  (a) => { return a }
interface ArrowFunctionExpression extends BaseNode {
  type: "ArrowFunctionExpression";
  params: FunctionParameter[];
  body: BlockStatement | Expression; // 表达式体时为 Expression，有花括号时为 BlockStatement
  async: boolean;
  expression: boolean;    // body 是 Expression（非 BlockStatement）时为 true
  generator?: boolean | null;  // 箭头函数不能是 generator，此字段为 null/false
  returnType?: TypeAnnotation | TSTypeAnnotation | null;
  typeParameters?: TypeParameterDeclaration | TSTypeParameterDeclaration | null;
  predicate?: FlowPredicate | null;
}

// FunctionParameter 是参数类型的联合
type FunctionParameter =
  | Identifier
  | Pattern              // 解构参数
  | RestElement          // ...rest
  | TSParameterProperty; // TypeScript: public/private/readonly 参数

```

#### 声明节点

```typescript
// var/let/const/using/await using x = 1
interface VariableDeclaration extends BaseNode {
  type: "VariableDeclaration";
  kind: "var" | "let" | "const" | "using" | "await using";
  declarations: VariableDeclarator[];
  declare?: boolean | null; // TypeScript: declare const x: string
}

// x = 1（VariableDeclaration 中的单个声明项）
interface VariableDeclarator extends BaseNode {
  type: "VariableDeclarator";
  id: Identifier | ArrayPattern | ObjectPattern | VoidPattern;
  init?: Expression | null;  // null 表示 let x 没有初始值
  definite?: boolean | null; // TypeScript: let x!: string
}

```

#### 语句节点

```typescript
// { ... }
interface BlockStatement extends BaseNode {
  type: "BlockStatement";
  body: Statement[];
  directives: Directive[]; // "use strict" 等
}

// 将表达式作为语句：foo()、a = 1 等
interface ExpressionStatement extends BaseNode {
  type: "ExpressionStatement";
  expression: Expression;
}

// return x
interface ReturnStatement extends BaseNode {
  type: "ReturnStatement";
  argument?: Expression | null; // return; 时为 null
}

// if (test) consequent else alternate
interface IfStatement extends BaseNode {
  type: "IfStatement";
  test: Expression;
  consequent: Statement;
  alternate?: Statement | null; // 无 else 时为 null
}

// throw err
interface ThrowStatement extends BaseNode {
  type: "ThrowStatement";
  argument: Expression;
}

// try { ... } catch (e) { ... } finally { ... }
interface TryStatement extends BaseNode {
  type: "TryStatement";
  block: BlockStatement;
  handler?: CatchClause | null;
  finalizer?: BlockStatement | null;
}

// while (test) body
interface WhileStatement extends BaseNode {
  type: "WhileStatement";
  test: Expression;
  body: Statement;
}

// for (init; test; update) body
interface ForStatement extends BaseNode {
  type: "ForStatement";
  init?: VariableDeclaration | Expression | null;
  test?: Expression | null;
  update?: Expression | null;
  body: Statement;
}

```

#### 模块节点

```typescript
// import { a, b as c } from 'mod'
// import DefaultExport from 'mod'
// import * as ns from 'mod'
interface ImportDeclaration extends BaseNode {
  type: "ImportDeclaration";
  specifiers: (ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier)[];
  source: StringLiteral;
  attributes?: ImportAttribute[] | null; // import ... with { type: "json" }
  importKind?: "type" | "typeof" | "value" | null; // Flow/TypeScript: import type
  phase?: "source" | "defer" | null; // import.source / import.defer 提案
  module?: boolean | null;
}

// { a } 或 { a as b }
interface ImportSpecifier extends BaseNode {
  type: "ImportSpecifier";
  local: Identifier;
  imported: Identifier | StringLiteral;
  importKind?: "type" | "typeof" | "value" | null;
}

// DefaultExport（import 中的默认导入）
interface ImportDefaultSpecifier extends BaseNode {
  type: "ImportDefaultSpecifier";
  local: Identifier;
}

// * as ns
interface ImportNamespaceSpecifier extends BaseNode {
  type: "ImportNamespaceSpecifier";
  local: Identifier;
}

// export { a, b as c }
// export const x = 1
// export { a } from 'mod'
interface ExportNamedDeclaration extends BaseNode {
  type: "ExportNamedDeclaration";
  declaration?: Declaration | null;          // export const x = 1 时有值
  specifiers: (ExportSpecifier | ExportDefaultSpecifier | ExportNamespaceSpecifier)[];
  source?: StringLiteral | null;             // export ... from 'mod' 时有值
  attributes?: ImportAttribute[] | null;
  exportKind?: "type" | "value" | null;      // export type { Foo }
}

// export default foo
interface ExportDefaultDeclaration extends BaseNode {
  type: "ExportDefaultDeclaration";
  declaration: Declaration | Expression;
  exportKind?: "value" | null;
}

// export * from 'mod'
interface ExportAllDeclaration extends BaseNode {
  type: "ExportAllDeclaration";
  source: StringLiteral;
  exported?: Identifier | StringLiteral | null; // export * as ns from 'mod'
  attributes?: ImportAttribute[] | null;
  exportKind?: "type" | "value" | null;
}

```

### 节点别名（类型联合）

`@babel/types` 定义了大量别名，在 visitor 中可以用别名一次匹配多种节点：

```typescript
// 主要别名（可直接在 traverse visitor 中使用）
type Expression =
  | Identifier | StringLiteral | NumericLiteral | BooleanLiteral | NullLiteral
  | TemplateLiteral | MemberExpression | CallExpression | NewExpression
  | BinaryExpression | UnaryExpression | LogicalExpression | AssignmentExpression
  | ConditionalExpression | SequenceExpression | ArrowFunctionExpression
  | FunctionExpression | ObjectExpression | ArrayExpression
  | TaggedTemplateExpression | YieldExpression | AwaitExpression
  | /* ... 更多 */;

type Statement =
  | ExpressionStatement | BlockStatement | ReturnStatement | IfStatement
  | VariableDeclaration | FunctionDeclaration | ClassDeclaration
  | ForStatement | ForInStatement | ForOfStatement | WhileStatement
  | DoWhileStatement | SwitchStatement | TryStatement | ThrowStatement
  | BreakStatement | ContinueStatement | LabeledStatement
  | ImportDeclaration | ExportNamedDeclaration | ExportDefaultDeclaration
  | ExportAllDeclaration | /* ... 更多 */;

type Declaration =
  | FunctionDeclaration | ClassDeclaration | VariableDeclaration
  | ExportNamedDeclaration | ExportDefaultDeclaration | ExportAllDeclaration
  | ImportDeclaration | /* ... 更多 */;

type Pattern =
  | AssignmentPattern | ArrayPattern | ObjectPattern | RestElement;

type Node =
  | Expression | Statement | Declaration | Pattern
  | File | Program | TemplateElement | SpreadElement | ObjectProperty
  | ObjectMethod | ClassBody | ClassMethod | ClassProperty
  | /* ... 所有节点的联合类型 */;

```

### 类型守卫函数（isXxx）

每个节点类型都有对应的类型守卫函数，**调用后 TypeScript 会自动收窄类型**：

```typescript
import * as t from "@babel/types";

// 基本签名：
// t.isXxx(node: object | null | undefined, opts?: object): node is Xxx

// opts 是可选的属性过滤器，所有字段都要匹配才返回 true
t.isIdentifier(node)                      // node is t.Identifier
t.isIdentifier(node, { name: "foo" })     // name === "foo" 时才匹配
t.isStringLiteral(node)                   // node is t.StringLiteral
t.isNumericLiteral(node)
t.isBooleanLiteral(node)
t.isNullLiteral(node)
t.isTemplateLiteral(node)
t.isMemberExpression(node)
t.isCallExpression(node)
t.isBinaryExpression(node)
t.isBinaryExpression(node, { operator: "+" })  // 只匹配 + 运算
t.isAssignmentExpression(node)
t.isObjectExpression(node)
t.isObjectProperty(node)
t.isArrayExpression(node)
t.isFunctionDeclaration(node)
t.isFunctionExpression(node)
t.isArrowFunctionExpression(node)
t.isVariableDeclaration(node)
t.isVariableDeclarator(node)
t.isBlockStatement(node)
t.isExpressionStatement(node)
t.isReturnStatement(node)
t.isIfStatement(node)
t.isImportDeclaration(node)
t.isExportNamedDeclaration(node)

// 别名守卫（匹配整个类别）
t.isExpression(node)    // node is t.Expression
t.isStatement(node)     // node is t.Statement
t.isDeclaration(node)   // node is t.Declaration
t.isLiteral(node)       // 匹配所有字面量类型
t.isScope(node)         // 有作用域的节点
t.isFunction(node)      // 所有函数形式
t.isClass(node)         // 所有 class 形式

```

### 断言函数（assertXxx）

`assertXxx` 与 `isXxx` 的区别：不匹配时**抛出 TypeError** 而非返回 false。  
适合在你确定类型正确但 TypeScript 无法推断的场合做强制收窄。

```typescript
// 基本签名：
// t.assertXxx(node: object | null | undefined, opts?: object): asserts node is Xxx

t.assertIdentifier(node);               // 断言后 node 类型为 t.Identifier
t.assertCallExpression(node);
t.assertFunctionDeclaration(node);

// 实际使用示例
function processCallee(node: t.Node) {
  t.assertMemberExpression(node);
  // 这里 node 已被收窄为 t.MemberExpression
  console.log(node.object, node.property);
}

```

### 构建器函数（完整签名）

```typescript
import * as t from "@babel/types";

// ---- 字面量 ----
t.identifier(name: string): t.Identifier
t.stringLiteral(value: string): t.StringLiteral
t.numericLiteral(value: number): t.NumericLiteral
t.booleanLiteral(value: boolean): t.BooleanLiteral
t.nullLiteral(): t.NullLiteral
t.bigIntLiteral(value: string): t.BigIntLiteral
t.regExpLiteral(pattern: string, flags?: string): t.RegExpLiteral

// templateLiteral 的 quasis 比 expressions 多一个
t.templateLiteral(
  quasis: t.TemplateElement[],
  expressions: (t.Expression | t.TSType)[]
): t.TemplateLiteral

t.templateElement(
  value: { raw: string; cooked?: string | null },
  tail?: boolean  // 默认 false，最后一个片段需要传 true
): t.TemplateElement

// ---- 表达式 ----
t.memberExpression(
  object: t.Expression | t.Super,
  property: t.Expression | t.Identifier | t.PrivateName,
  computed?: boolean,  // 默认 false
  optional?: boolean | null
): t.MemberExpression

t.callExpression(
  callee: t.Expression | t.Super | t.V8IntrinsicIdentifier,
  args: (t.Expression | t.SpreadElement | t.ArgumentPlaceholder)[],
  typeArguments?: t.TypeParameterInstantiation | t.TSTypeParameterInstantiation | null
): t.CallExpression

t.binaryExpression(
  operator: "+" | "-" | "/" | "%" | "*" | "**" | "&" | "|" | ">>" | ">>>"
    | "<<" | "^" | "==" | "===" | "!=" | "!==" | "in" | "instanceof"
    | ">" | "<" | ">=" | "<=" | "|>",
  left: t.Expression | t.PrivateName,
  right: t.Expression
): t.BinaryExpression

t.assignmentExpression(
  operator: "=" | "+=" | "-=" | "/=" | "%=" | "*=" | "**="
    | "&=" | "|=" | ">>=" | ">>>=" | "<<=" | "^="
    | "||=" | "&&=" | "??=",
  left: t.LVal,
  right: t.Expression
): t.AssignmentExpression

t.objectExpression(
  properties: (t.ObjectMethod | t.ObjectProperty | t.SpreadElement)[]
): t.ObjectExpression

t.objectProperty(
  key: t.Expression | t.Identifier | t.StringLiteral | t.NumericLiteral | t.PrivateName,
  value: t.Expression | t.PatternLike,
  computed?: boolean,   // 默认 false
  shorthand?: boolean,  // 默认 false
  decorators?: t.Decorator[] | null
): t.ObjectProperty

t.objectMethod(
  kind: "method" | "get" | "set",
  key: t.Expression | t.Identifier | t.StringLiteral | t.NumericLiteral | t.PrivateName,
  params: t.FunctionParameter[],
  body: t.BlockStatement,
  computed?: boolean,
  generator?: boolean,
  async?: boolean
): t.ObjectMethod

t.arrayExpression(
  elements?: (null | t.Expression | t.SpreadElement)[]
): t.ArrayExpression

t.spreadElement(argument: t.Expression): t.SpreadElement

// ---- 函数 ----
t.functionDeclaration(
  id: t.Identifier | null,
  params: t.FunctionParameter[],
  body: t.BlockStatement,
  generator?: boolean,  // 默认 false
  async?: boolean       // 默认 false
): t.FunctionDeclaration

t.functionExpression(
  id: t.Identifier | null | undefined,
  params: t.FunctionParameter[],
  body: t.BlockStatement,
  generator?: boolean,
  async?: boolean
): t.FunctionExpression

t.arrowFunctionExpression(
  params: t.FunctionParameter[],
  body: t.BlockStatement | t.Expression,
  async?: boolean  // 默认 false
): t.ArrowFunctionExpression

// ---- 语句 ----
t.blockStatement(
  body: t.Statement[],
  directives?: t.Directive[]
): t.BlockStatement

t.expressionStatement(expression: t.Expression): t.ExpressionStatement
t.returnStatement(argument?: t.Expression | null): t.ReturnStatement

t.ifStatement(
  test: t.Expression,
  consequent: t.Statement,
  alternate?: t.Statement | null
): t.IfStatement

t.throwStatement(argument: t.Expression): t.ThrowStatement
t.tryStatement(
  block: t.BlockStatement,
  handler?: t.CatchClause | null,
  finalizer?: t.BlockStatement | null
): t.TryStatement

// ---- 声明 ----
t.variableDeclaration(
  kind: "var" | "let" | "const" | "using" | "await using",
  declarations: t.VariableDeclarator[]
): t.VariableDeclaration

t.variableDeclarator(
  id: t.LVal,
  init?: t.Expression | null
): t.VariableDeclarator

// ---- 模块 ----
t.importDeclaration(
  specifiers: (t.ImportSpecifier | t.ImportDefaultSpecifier | t.ImportNamespaceSpecifier)[],
  source: t.StringLiteral,
  attributes?: t.ImportAttribute[] | null
): t.ImportDeclaration

t.importSpecifier(
  local: t.Identifier,
  imported: t.Identifier | t.StringLiteral,
  importKind?: "type" | "typeof" | "value" | null
): t.ImportSpecifier

t.importDefaultSpecifier(local: t.Identifier): t.ImportDefaultSpecifier
t.importNamespaceSpecifier(local: t.Identifier): t.ImportNamespaceSpecifier

t.exportNamedDeclaration(
  declaration?: t.Declaration | null,
  specifiers?: (t.ExportSpecifier | t.ExportDefaultSpecifier | t.ExportNamespaceSpecifier)[],
  source?: t.StringLiteral | null,
  attributes?: t.ImportAttribute[] | null
): t.ExportNamedDeclaration

t.exportSpecifier(
  local: t.Identifier,
  exported: t.Identifier | t.StringLiteral
): t.ExportSpecifier

t.exportDefaultDeclaration(
  declaration: t.Declaration | t.Expression
): t.ExportDefaultDeclaration

```

### 节点工具函数

```typescript
// 深度克隆节点（包含所有子节点）
// withoutLocations: true 时去掉位置信息（默认 false）
t.cloneNode<T extends t.Node>(node: T, deep?: boolean, withoutLocations?: boolean): T

// 浅克隆（只克隆顶层，子节点共享引用）
t.shallowEqual(actual: object, expected: object): boolean

// 递归清除节点的位置信息、注释等元数据
// opts.preserveComments: 保留注释（默认 false）
t.removePropertiesDeep(node: t.Node, opts?: { preserveComments?: boolean }): t.Node

// 移除单个节点的位置/注释等非核心属性
t.removeProperties(node: t.Node, opts?: { preserveComments?: boolean }): void

// 判断节点是否表示纯值（无副作用）
t.isPureish(node: t.Node): boolean

// 获取节点的所有 binding 标识符
t.getBindingIdentifiers(node: t.Node, duplicates?: boolean, outerOnly?: boolean): { [name: string]: t.Identifier | t.Identifier[] }

// 判断两个节点是否相等（深度比较）
t.isNodesEquivalent(a: t.Node, b: t.Node): boolean

// 判断节点是否是引用（而非赋值目标）
t.isReferenced(node: t.Node, parent: t.Node, grandparent?: t.Node): boolean

// 获取节点的 type 字段，考虑别名
t.toComputedKey(node: t.ObjectMethod | t.ObjectProperty | t.ClassMethod | t.ClassProperty): t.Expression

```

---

## @babel/traverse 类型详解

### traverse() 函数签名

```typescript
import traverse from "@babel/traverse";
import * as t from "@babel/types";

// 无 state 时（最常用形式）
function traverse(
  parent: t.Node,
  opts?: TraverseOptions,
  scope?: Scope,
  state?: any,
  parentPath?: NodePath
): void;

// 有 state 时（泛型形式，state 类型安全）
function traverse<S>(
  parent: t.Node,
  opts: TraverseOptions<S>,
  scope: Scope | undefined,
  state: S,
  parentPath?: NodePath
): void;

```

### TraverseOptions / Visitor 接口

```typescript
// Visitor 是 TraverseOptions 的核心
// 键是节点类型字符串，值是访问函数或 { enter, exit } 对象
type Visitor<S = unknown> =
  // 每个节点类型名都可以作为键
  & { [N in t.Node as N["type"]]?: VisitNode<S, N> }
  // 别名也可以作为键（Function、Expression、Statement 等）
  & { [K in keyof t.Aliases]?: VisitNode<S, t.Aliases[K]> }
  // 多类型用 | 合并：'StringLiteral|NumericLiteral'
  & { [k: `${string}|${string}`]: VisitNode<S, t.Node> }
  // 入口/出口处理
  & VisitNodeObject<S, t.Node>;

// 访问节点可以是函数或对象
type VisitNode<S, P extends t.Node> =
  | VisitNodeFunction<S, P>
  | VisitNodeObject<S, P>;

// 函数形式
type VisitNodeFunction<S, P extends t.Node> =
  (this: S, path: NodePath<P>, state: S) => void;

// 对象形式（enter/exit）
interface VisitNodeObject<S, P extends t.Node> {
  enter?: VisitNodeFunction<S, P>;
  exit?: VisitNodeFunction<S, P>;
}

```

### NodePath<T> 接口（完整字段）

`NodePath<T>` 是对节点的包装，`T` 是具体的节点类型（默认为 `t.Node`）。

```typescript
interface NodePath<T extends t.Node = t.Node> {
  // ---- 核心属性 ----
  node: T;                      // 当前 AST 节点
  type: T["type"] | undefined;  // 节点类型字符串
  parent: t.Node;               // 父节点（AST 节点，非 path）
  parentPath: NodePath | null;  // 父节点的 path（根节点时为 null）
  scope: Scope;                 // 当前作用域

  // ---- 位置信息 ----
  key: string | number | null;  // 本节点在父节点中的字段名（如 "body"、"left"、0）
  listKey: string | null;       // 本节点所在的数组字段名（如 "body"），非数组时为 null
  inList: boolean;              // 本节点是否在数组中

  // ---- 容器信息 ----
  container: t.Node | t.Node[] | null; // 包含本节点的容器（数组或父节点字段）
  hub: Hub;                     // 全局上下文

  // ---- 状态标记 ----
  removed: boolean;   // 是否已被 remove()
  replaced: boolean;  // 是否已被 replaceWith()
  skipped: boolean;   // 是否已被 skip()

  // ---- 用户数据 ----
  data: Record<string | symbol, unknown>; // 可自由附加数据（如标记"已处理"）
  state: any; // traverse 传入的 state

  // ---- 辅助 ----
  contexts: TraversalContext[];
}

```

### NodePath 上的方法

#### 类型判断方法

```typescript
// path.isXxx(opts?) 的形式对所有节点类型都有
// 返回 boolean，同时收窄 path 的泛型类型
path.isIdentifier(opts?: { name?: string }): this is NodePath<t.Identifier>
path.isStringLiteral(opts?: { value?: string }): this is NodePath<t.StringLiteral>
path.isCallExpression(): this is NodePath<t.CallExpression>
path.isMemberExpression(): this is NodePath<t.MemberExpression>
path.isFunctionDeclaration(): this is NodePath<t.FunctionDeclaration>
path.isExpression(): this is NodePath<t.Expression>
path.isStatement(): this is NodePath<t.Statement>
// ... 200+ 个 isXxx 方法，与 t.isXxx 一一对应

```

#### 替换节点

```typescript
// 用单个节点替换当前节点
path.replaceWith(node: t.Node | NodePath): void

// 用多个节点替换（当前节点必须在语句列表中）
path.replaceWithMultiple(nodes: t.Node[]): NodePath[]

// 用代码字符串替换（内部会解析代码）
path.replaceWithSourceString(replacement: string): void

// 将表达式替换为语句序列，返回包裹函数的调用表达式
path.replaceExpressionWithStatements(nodes: t.Statement[]): t.Node

```

#### 插入节点

```typescript
// 在当前节点之前插入（当前节点必须在语句列表中）
path.insertBefore(nodes: t.Node | t.Node[]): NodePath[]

// 在当前节点之后插入
path.insertAfter(nodes: t.Node | t.Node[]): NodePath[]

```

#### 删除节点

```typescript
path.remove(): void

```

#### 控制遍历

```typescript
// 跳过当前节点的所有子节点（本节点仍处理，但不再向下遍历）
path.skip(): void

// 立即停止整个 traverse 遍历
path.stop(): void

// 对当前节点的子节点发起遍历（手动递归）
path.traverse(opts: TraverseOptions, state?: any): void

```

#### 查找父节点

```typescript
// 向上查找满足条件的祖先 path（包含当前节点）
// 回调返回 true 时停止，返回该 path
path.find(callback: (path: NodePath) => boolean): NodePath | null

// 向上查找满足条件的祖先 path（不包含当前节点）
path.findParent(callback: (path: NodePath) => boolean): NodePath | null

// 向上找最近的函数作用域的 path
path.getFunctionParent(): NodePath<t.Function> | null

// 向上找最近的语句 path
path.getStatementParent(): NodePath<t.Statement> | null

// 获取从根到当前节点的所有祖先 path（不含当前）
path.getAncestry(): NodePath[]

// 判断某个 path 是否是当前 path 的祖先
path.isAncestor(maybeDescendant: NodePath): boolean

// 判断某个 path 是否是当前 path 的后代
path.isDescendant(maybeAncestor: NodePath): boolean

```

#### 获取子路径

```typescript
// 获取某个字段的子 path
// key 是字段名，listKey 是数组下标
path.get(key: string): NodePath | NodePath[]
path.get(key: string, context?: boolean): NodePath<t.Node> | NodePath<t.Node>[]

// 示例
const bodyPaths = path.get("body") as NodePath[];
const firstArg = path.get("arguments.0") as NodePath;

```

#### 求值

```typescript
// 静态求值：尝试计算节点的常量值
// confident=true 时才可信，否则 value 无意义
path.evaluate(): { confident: boolean; value: any; deopt?: NodePath }

// 只返回布尔值的求值（用于条件判断）
path.evaluateTruthy(): boolean | undefined

```

#### 模式匹配

```typescript
// 判断 MemberExpression 是否匹配指定模式
// 如：path.matchesPattern("console.log")
path.matchesPattern(pattern: string, allowPartial?: boolean): boolean

```

#### Binding 相关

```typescript
// 获取当前节点中所有 binding 的 Identifier 节点
path.getBindingIdentifiers(duplicates?: boolean): { [name: string]: t.Identifier | t.Identifier[] }

// 获取外层 binding 的 Identifier（解构时有区别）
path.getOuterBindingIdentifiers(duplicates?: boolean): { [name: string]: t.Identifier }

// 获取所有 binding 的 NodePath
path.getBindingIdentifierPaths(duplicates?: boolean, outerOnly?: boolean): { [name: string]: NodePath<t.Identifier> }

```

### Scope 接口

```typescript
interface Scope {
  // ---- 基础属性 ----
  uid: number;          // 作用域唯一 ID
  path: NodePath;       // 产生此作用域的节点 path
  block: t.Node;        // 产生此作用域的节点（与 path.node 相同）
  parent: Scope;        // 父作用域
  hub: Hub;

  // ---- 绑定信息 ----
  // 当前作用域内所有变量绑定（键为变量名）
  bindings: { [name: string]: Binding };

  // 当前作用域内所有变量引用（只有键，值为 true）
  references: { [name: string]: true };

  // ---- 查询方法 ----

  // 获取变量绑定（向上查找父作用域）
  getBinding(name: string): Binding | undefined;

  // 获取仅在当前作用域的绑定（不查父作用域）
  getOwnBinding(name: string): Binding | undefined;

  // 判断变量是否在当前或父作用域中有绑定
  hasBinding(name: string, opts?: { noGlobals?: boolean; noUids?: boolean }): boolean;

  // 判断变量是否仅在当前作用域绑定
  hasOwnBinding(name: string): boolean;

  // 判断变量是否被引用（有使用者）
  hasReference(name: string): boolean;

  // ---- 重命名 ----

  // 重命名变量（自动处理所有引用点，包括声明和使用）
  rename(oldName: string, newName?: string, block?: t.Node): void;

  // ---- 生成新标识符 ----

  // 生成一个当前作用域内唯一的 uid（字符串）
  generateUid(name?: string): string;

  // 生成唯一 uid 并返回 Identifier 节点
  generateUidIdentifier(name?: string): t.Identifier;

  // 基于某个节点名称生成唯一 uid
  generateUidIdentifierBasedOnNode(node: t.Node, defaultName?: string): t.Identifier;

  // ---- 作用域操作 ----

  // 在当前作用域发起遍历
  traverse(node: t.Node, opts: TraverseOptions, state?: any): void;

  // 将引用推送到根作用域（提升变量）
  push(opts: {
    id: t.LVal;
    init?: t.Expression | null;
    unique?: boolean;
    kind?: "var" | "let" | "const";
  }): void;

  // 删除当前作用域的绑定信息（强制重新爬取）
  removeBinding(name: string): void;

  // 重新爬取当前作用域的绑定信息
  crawl(): void;

  // 判断标识符是否是静态的（可以安全求值）
  isStatic(node: t.Node): boolean;

  // 获取所有绑定（包括父作用域）
  getAllBindings(): { [name: string]: Binding };

  // 获取所有绑定名称（包括父作用域）
  getAllBindingNames(): string[];
}

```

### Binding 类

`Binding` 表示一个变量的绑定信息，通过 `scope.getBinding(name)` 或 `scope.bindings[name]` 获取：

```typescript
type BindingKind =
  | "var"           // var 声明
  | "let"           // let 声明
  | "const"         // const 声明
  | "module"        // import 声明
  | "hoisted"       // function 声明（提升）
  | "param"         // 函数参数
  | "local"         // 函数表达式的 id（如 const fn = function foo() {} 中的 foo）
  | "unknown";      // 无法确定

class Binding {
  identifier: t.Identifier;      // 绑定的 Identifier 节点
  scope: Scope;                  // 绑定所在的作用域
  path: NodePath;                // 声明处的 path
  kind: BindingKind;

  referenced: boolean;           // 是否被引用过
  references: number;            // 被引用次数
  referencePaths: NodePath[];    // 所有引用处的 path

  constant: boolean;             // 是否是常量（没有赋值操作）
  constantViolations: NodePath[]; // 所有对该变量赋值的 path

  // 标记一次引用
  reference(path: NodePath): void;
  // 取消一次引用
  dereference(): void;
  // 标记一次赋值
  reassign(path: NodePath): void;
}

```

---

## @babel/generator 类型详解

### generate() 函数签名

```typescript
import generate from "@babel/generator";
import * as t from "@babel/types";

// ast 可以是任意 Node，不只是 File
// code 是原始代码（用于 source map）
// 如果是多文件场景，code 可以是文件名到代码内容的映射
function generate(
  ast: t.Node,
  opts?: GeneratorOptions,
  code?: string | { [filename: string]: string }
): GeneratorResult;

```

### GeneratorOptions 接口（所有字段）

```typescript
interface GeneratorOptions {
  // ---- 注释控制 ----

  // 在注入代码之前添加的注释（如块级帮助函数）
  auxiliaryCommentBefore?: string;

  // 在注入代码之后添加的注释
  auxiliaryCommentAfter?: string;

  // 是否输出注释（默认 true）
  comments?: boolean;

  // 自定义注释过滤器（返回 true 时输出该注释）
  shouldPrintComment?: (comment: string) => boolean;

  // ---- 格式控制 ----

  // 是否紧凑模式（去掉大部分空格）
  // true: 强制紧凑；false: 强制非紧凑；"auto": 跟随 minified 选项
  compact?: boolean | "auto";

  // 是否适度减少空格（比 compact 弱，默认 false）
  concise?: boolean;

  // 是否完全压缩（同时开启 compact，默认 false）
  minified?: boolean;

  // 尝试保留原始行号（可能影响代码可读性，默认 false）
  retainLines?: boolean;

  // 保留函数调用的括号（防止某些压缩工具误删，默认 false）
  retainFunctionParens?: boolean;

  // ---- 字符串/特殊语法 ----

  // 关联的文件名（影响 source map 的 file 字段）
  filename?: string;

  // 是否将字符串输出为 JSON 兼容格式（全部用 Unicode 转义，默认 false）
  jsonCompatibleStrings?: boolean;

  // jsesc 库的选项（控制字符串转义行为）
  // 常用选项：{ minimal: true } 只转义必须转义的字符
  jsescOption?: {
    quotes?: "single" | "double" | "backtick";
    minimal?: boolean;
    numbers?: "decimal" | "hexadecimal" | "octal" | "binary";
    indent?: string;
    indentLevel?: number;
    json?: boolean;
    es6?: boolean;
    escapeEverything?: boolean;
    wrap?: boolean;
    isScriptContext?: boolean;
    compact?: boolean;
    lowercaseHex?: boolean;
  };

  // ---- 特殊语法选项 ----

  // decorator 放在 export 前还是后（默认 false 即放在后面）
  decoratorsBeforeExport?: boolean;

  // Record/Tuple 的语法类型：#[...] 和 #{ } 或 |[ ]| 和 |{ }|（默认 "hash"）
  recordAndTupleSyntaxType?: "hash" | "bar";

  // |> 管道运算符的 topic token（默认 "%"）
  topicToken?: "%" | "#" | "@@" | "^^";

  // import attributes 使用 with 还是 assert 关键字
  importAttributesKeyword?: "with" | "assert" | "with-legacy";

  // ---- Source Map ----

  // 是否生成 source map（默认 false）
  sourceMaps?: boolean;

  // source map 的根路径
  sourceRoot?: string;

  // source map 中的文件名
  sourceFileName?: string;

  // 输入的 source map（用于 map 的 map）
  inputSourceMap?: string | object;

  // ---- 实验性 ----

  // 实验性：尽量保留原始代码格式（需要 @babel/parser 的 tokens 选项）
  experimental_preserveFormat?: boolean;
}

```

### GeneratorResult 接口

```typescript
interface GeneratorResult {
  // 生成的代码字符串
  code: string;

  // source map 对象（sourceMaps=false 时为 null）
  map: {
    version: number;
    sources: string[];
    names: string[];
    sourceRoot?: string;
    sourcesContent?: string[];
    mappings: string;   // VLQ 编码的位置映射
    file: string;
  } | null;

  // 解码后的 source map（内部使用，通常不需要）
  decodedMap?: DecodedSourceMap;

  // 原始映射数组（内部使用）
  rawMappings?: Mapping[];
}

```

---

## @babel/core 类型详解

### 转换函数签名

```typescript
import {
  transformSync,
  transformAsync,
  transform,
  transformFileSync,
  transformFileAsync,
  parseSync,
  parseAsync,
} from "@babel/core";

// 同步转换代码字符串
transformSync(
  code: string,
  options?: TransformOptions
): BabelFileResult | null;

// 异步转换代码字符串（支持异步插件）
transformAsync(
  code: string,
  options?: TransformOptions
): Promise<BabelFileResult | null>;

// 回调形式（较少使用）
transform(
  code: string,
  options: TransformOptions | undefined,
  callback: (err: Error | null, result: BabelFileResult | null) => void
): void;

// 同步转换文件（自动读取文件内容）
transformFileSync(
  filename: string,
  options?: TransformOptions
): BabelFileResult | null;

// 异步转换文件
transformFileAsync(
  filename: string,
  options?: TransformOptions
): Promise<BabelFileResult | null>;

// 只解析，不转换（同步）
parseSync(
  code: string,
  options?: TransformOptions
): t.File | null;

// 只解析，不转换（异步）
parseAsync(
  code: string,
  options?: TransformOptions
): Promise<t.File | null>;

```

### BabelFileResult 接口

```typescript
interface BabelFileResult {
  // 生成的代码（code: false 时为 null）
  code: string | null | undefined;

  // source map 对象（sourceMaps: false 时为 null）
  map: object | null | undefined;

  // AST（ast: true 时才有值）
  ast: t.File | null | undefined;

  // 外部依赖（被 ignore 匹配到的文件）
  ignored?: boolean;

  // 外部依赖文件路径
  externalDependencies?: Set<string>;
}

```

### TransformOptions 接口（重要字段）

```typescript
interface TransformOptions {
  // ---- 输入文件信息 ----

  // 关联的文件名（影响配置文件查找、source map、错误信息）
  filename?: string;

  // 相对文件名（用于 source map 的 sources 字段）
  filenameRelative?: string;

  // 工作目录（配置文件相对路径基准）
  cwd?: string;

  // ---- 输出控制 ----

  // 是否生成 code 字符串（默认 true）
  code?: boolean;

  // 是否在结果中包含 AST（默认 false，开启后 ast 字段有值）
  ast?: boolean;

  // 是否克隆输入 AST（默认 true，避免 traverse 修改原始 AST）
  cloneInputAst?: boolean;

  // ---- 插件与预设 ----

  // 插件列表
  // 可以是：字符串、[字符串, options]、插件函数、[插件函数, options]
  plugins?: PluginItem[];

  // 预设列表（与 plugins 格式相同）
  presets?: PluginItem[];

  // ---- 语法模式 ----

  // 模块类型（同 ParserOptions.sourceType）
  sourceType?: "script" | "module" | "commonjs" | "unambiguous";

  // ---- 配置文件 ----

  // 项目根配置文件路径（false 禁用）
  configFile?: string | false | boolean;

  // 是否搜索 .babelrc（默认 true）
  babelrc?: boolean;

  // 哪些包允许搜索 babelrc
  babelrcRoots?: boolean | MatchPattern | MatchPattern[];

  // 项目根目录
  root?: string;

  // 根目录查找模式
  rootMode?: "root" | "upward" | "upward-optional";

  // 当前环境（读取 env[envName] 的配置，默认读 NODE_ENV 或 "development"）
  envName?: string;

  // ---- Source Map ----

  // 是否生成 source map
  // true: 独立 map 对象；"inline": 追加到代码末尾；"both": 两者都要
  sourceMaps?: boolean | "inline" | "both";

  // source map 中的文件名
  sourceFileName?: string;

  // source map 根路径
  sourceRoot?: string;

  // ---- 代码生成 ----

  // 保留原始行号（默认 false）
  retainLines?: boolean;

  // 紧凑输出（默认 "auto"）
  compact?: boolean | "auto";

  // 压缩输出（默认 false）
  minified?: boolean;

  // 是否保留注释（默认 true）
  comments?: boolean;

  // 自定义注释过滤
  shouldPrintComment?: (comment: string) => boolean;

  // 传给 parser 的额外选项
  parserOpts?: ParserOptions;

  // 传给 generator 的额外选项
  generatorOpts?: GeneratorOptions;

  // ---- 条件配置 ----

  // 环境特定配置
  env?: { [envKey: string]: TransformOptions };

  // 条件覆盖配置
  overrides?: TransformOptions[];

  // 包含匹配的文件（与 test 同义）
  test?: MatchPattern | MatchPattern[];
  include?: MatchPattern | MatchPattern[];

  // 排除匹配的文件
  exclude?: MatchPattern | MatchPattern[];
  ignore?: MatchPattern | MatchPattern[];
  only?: MatchPattern | MatchPattern[];

  // ---- 优化 ----

  // Babel 可以对代码做的假设（用于优化输出体积）
  assumptions?: { [assumption: string]: boolean };

  // 目标环境（支持 browserslist 格式）
  targets?: string | string[] | { [key: string]: string };
}

```

### PluginObj 接口（插件格式）

编写 Babel 插件时，插件函数返回一个 `PluginObj`：

```typescript
import { PluginObj, PluginPass } from "@babel/core";
import traverse, { NodePath } from "@babel/traverse";
import * as t from "@babel/types";

// S 是 state 的类型，默认是 PluginPass
// PluginPass 是 Babel 传给插件的内置 state 对象
type PluginObj<S extends PluginPass = PluginPass> = {
  // 插件名称（可选，用于错误信息）
  name?: string;

  // 在所有转换开始前调用（this 是 state 实例）
  pre?: (this: S, file: BabelFile) => void | Promise<void>;

  // AST 访问者（核心）
  visitor?: Visitor<S>;

  // 在所有转换完成后调用
  post?: (this: S, file: BabelFile) => void | Promise<void>;

  // 修改 parser/generator 选项
  manipulateOptions?: (
    options: TransformOptions,
    parserOpts: ParserOptions
  ) => void;

  // 继承另一个插件
  inherits?: PluginAPI;
};

// PluginPass 是 state 的内置类型（插件 visitor 里的 this 和 state 参数）
class PluginPass {
  file: BabelFile;
  key: string | undefined | null;
  opts: object;                  // 插件的配置选项
  cwd: string;                   // 工作目录
  filename: string | undefined;  // 当前文件路径

  // 存/取任意数据（跨 visitor 共享状态）
  set(key: unknown, val: unknown): void;
  get(key: unknown): any;

  // 判断是否可以使用某个 helper
  availableHelper(name: string, versionRange?: string): boolean;

  // 添加 helper import（插件注入 helper 函数时使用）
  addHelper(name: string): t.Expression;

  // 生成带代码位置的错误信息
  buildCodeFrameError(node: t.Node, msg: string, Error?: typeof Error): Error;
}

```

---

## TypeScript 使用模式

### 1\. 正确为 NodePath 加泛型

```typescript
import traverse, { NodePath } from "@babel/traverse";
import * as t from "@babel/types";

const ast = parse(`foo(1, 2)`);

traverse(ast, {
  // visitor 键名决定了 path 的泛型类型
  // 这里 path 自动被推断为 NodePath<t.CallExpression>
  CallExpression(path) {
    // path.node 类型是 t.CallExpression，有完整类型提示
    const callee = path.node.callee;       // t.Expression | t.Super | t.V8IntrinsicIdentifier
    const args = path.node.arguments;      // (t.Expression | t.SpreadElement | ...)[]
  },

  // 也可以显式标注（当 TypeScript 推断失败时）
  "StringLiteral|NumericLiteral"(path: NodePath<t.StringLiteral | t.NumericLiteral>) {
    console.log(path.node.value);
  },
});

```

### 2\. 用 isXxx() 做类型收窄

```typescript
traverse(ast, {
  CallExpression(path) {
    const callee = path.node.callee;
    // callee 类型是 t.Expression | t.Super | t.V8IntrinsicIdentifier
    // 直接访问 .name 会报错

    // 用 isXxx 收窄
    if (t.isIdentifier(callee)) {
      // 这里 callee 类型收窄为 t.Identifier
      console.log(callee.name); // 类型安全
    }

    if (t.isMemberExpression(callee)) {
      // 这里 callee 类型收窄为 t.MemberExpression
      // 继续收窄 property
      if (!callee.computed && t.isIdentifier(callee.property)) {
        console.log(callee.property.name);
      }
    }

    // 带 opts 的收窄（同时检查属性值）
    if (t.isIdentifier(callee, { name: "console" })) {
      // callee 是名为 "console" 的 Identifier
    }
  },
});

```

### 3\. state 对象的类型标注

```typescript
import { NodePath, Visitor } from "@babel/traverse";
import * as t from "@babel/types";

// 定义 state 类型
interface MyState {
  functionCount: number;
  stringLiterals: string[];
  filename: string;
}

const initialState: MyState = {
  functionCount: 0,
  stringLiterals: [],
  filename: "",
};

// 方式一：traverse 的泛型形式（state 完全类型安全）
traverse<MyState>(
  ast,
  {
    FunctionDeclaration(path, state) {
      // state 类型是 MyState，有类型提示
      state.functionCount++;
    },
    StringLiteral(path, state) {
      state.stringLiterals.push(path.node.value);
    },
  },
  undefined,
  initialState
);

console.log(initialState.functionCount); // 访问结果

// 方式二：定义 Visitor 变量（复用 visitor）
const myVisitor: Visitor<MyState> = {
  FunctionDeclaration(path, state) {
    state.functionCount++;
  },
  StringLiteral(path, state) {
    state.stringLiterals.push(path.node.value);
  },
};

traverse<MyState>(ast, myVisitor, undefined, initialState);

```

### 4\. 编写类型安全的 Babel 插件

```typescript
import { PluginObj, PluginPass } from "@babel/core";
import * as t from "@babel/types";

// 定义插件选项类型
interface MyPluginOptions {
  stripConsole?: boolean;
  targetVar?: string;
}

// 扩展 PluginPass 以添加自定义字段
interface MyPluginState extends PluginPass {
  opts: MyPluginOptions; // 覆盖 opts 的类型
  removedCount: number;
}

// 导出插件函数
export default function myPlugin(): PluginObj<MyPluginState> {
  return {
    name: "my-plugin",

    pre(this: MyPluginState) {
      this.removedCount = 0;
    },

    visitor: {
      ExpressionStatement(path, state) {
        if (!state.opts.stripConsole) return;

        const expr = path.node.expression;
        if (
          t.isCallExpression(expr) &&
          t.isMemberExpression(expr.callee) &&
          t.isIdentifier(expr.callee.object, { name: "console" })
        ) {
          path.remove();
          state.removedCount++;
        }
      },

      Identifier(path, state) {
        const targetVar = state.opts.targetVar;
        if (!targetVar) return;

        if (
          path.node.name === targetVar &&
          path.isReferenced()
        ) {
          path.replaceWith(t.identifier("__renamed__" + targetVar));
        }
      },
    },

    post(this: MyPluginState) {
      if (this.opts.stripConsole) {
        console.info(`Removed ${this.removedCount} console calls`);
      }
    },
  };
}

```

### 5\. 遍历时避免 any 的最佳实践

```typescript
import traverse, { NodePath } from "@babel/traverse";
import * as t from "@babel/types";

// 不好的写法：丢失类型信息
traverse(ast, {
  CallExpression(path: any) { // any 丢失所有类型检查
    path.node.callee.name; // 不安全，callee 不一定有 name
  },
});

// 好的写法一：利用 visitor 键名自动推断
traverse(ast, {
  CallExpression(path) { // path 自动推断为 NodePath<t.CallExpression>
    const { callee } = path.node;
    if (t.isIdentifier(callee)) { // 用 isXxx 收窄
      callee.name; // 类型安全
    }
  },
});

// 好的写法二：提取为具名函数，显式标注类型
function visitCallExpression(path: NodePath<t.CallExpression>): void {
  const { callee, arguments: args } = path.node;

  if (t.isIdentifier(callee)) {
    console.log(`调用函数: ${callee.name}`);
  } else if (t.isMemberExpression(callee) && !callee.computed) {
    t.assertIdentifier(callee.object);
    t.assertIdentifier(callee.property);
    console.log(`调用方法: ${callee.object.name}.${callee.property.name}`);
  }
}

traverse(ast, { CallExpression: visitCallExpression });

// 好的写法三：处理 NodePath 数组（path.get 返回联合类型）
traverse(ast, {
  ArrayExpression(path) {
    const elements = path.get("elements"); // NodePath<...>[]
    if (!Array.isArray(elements)) return;

    for (const element of elements) {
      if (element.isStringLiteral()) {
        // element 收窄为 NodePath<t.StringLiteral>
        console.log(element.node.value);
      }
    }
  },
});

```

### 6\. 处理 MemberExpression 的计算属性问题

由于 `MemberExpression` 是联合类型，`property` 的类型取决于 `computed` 字段：

```typescript
traverse(ast, {
  MemberExpression(path) {
    const { node } = path;

    if (node.computed) {
      // node.property 类型是 t.Expression
      // node 类型收窄为 MemberExpressionComputed
      console.log("计算属性:", node.property.type);
    } else {
      // node.property 类型是 t.Identifier | t.PrivateName
      if (t.isIdentifier(node.property)) {
        console.log("属性名:", node.property.name);
      }
    }
  },
});

```

### 7\. 使用 path.scope 做安全重命名

```typescript
import traverse from "@babel/traverse";

traverse(ast, {
  Identifier(path) {
    const { name } = path.node;
    if (!/^_0x[0-9a-f]+$/i.test(name)) return;

    const binding = path.scope.getBinding(name);
    if (!binding) return;

    // 确认是声明处（避免重复重命名）
    if (binding.path.node !== path.node) return;

    // generateUid 保证新名称在当前作用域不冲突
    const newName = path.scope.generateUid("var");
    // rename 自动更新所有引用（binding.referencePaths）
    path.scope.rename(name, newName);
  },
});

```

### 8\. 完整的 TypeScript 工作流示例

```typescript
import { parse } from "@babel/parser";
import traverse, { NodePath } from "@babel/traverse";
import generate from "@babel/generator";
import * as t from "@babel/types";

const sourceCode = `
import { foo } from "bar";
const result = foo(1, "hello", true);
`;

// 1. 解析（返回类型明确为 t.File）
const ast: t.File = parse(sourceCode, {
  sourceType: "module",
  plugins: ["typescript"],
});

// 2. 遍历并修改
traverse(ast, {
  // ImportDeclaration 的 path 类型为 NodePath<t.ImportDeclaration>
  ImportDeclaration(path) {
    // source.value 是字符串，类型安全
    if (path.node.source.value === "bar") {
      path.node.source = t.stringLiteral("baz");
    }
  },

  // CallExpression 的 path 类型为 NodePath<t.CallExpression>
  CallExpression(path) {
    const { callee, arguments: args } = path.node;

    if (!t.isIdentifier(callee, { name: "foo" })) return;

    // 将所有参数中的字符串字面量转为大写
    const newArgs = args.map((arg) => {
      if (t.isStringLiteral(arg)) {
        return t.stringLiteral(arg.value.toUpperCase());
      }
      return arg;
    });

    path.replaceWith(
      t.callExpression(callee, newArgs)
    );
    path.skip(); // 防止递归处理新节点
  },
});

// 3. 生成代码
const { code, map } = generate(ast, {
  comments: true,
  jsescOption: { minimal: true },
});

console.log(code);
// import { foo } from "baz";
// const result = foo(1, "HELLO", true);

```

---

## 注意事项与踩坑

### @babel/traverse 的默认导出问题

```typescript
// 编译到 CJS 时，traverse 是 module.exports.default
// 需要这样导入（配合 esModuleInterop: true）：
import traverse from "@babel/traverse";

// 如果不用 esModuleInterop，需要这样：
import _traverse from "@babel/traverse";
const traverse = (_traverse as any).default ?? _traverse;

// @babel/generator 同理
import _generate from "@babel/generator";
const generate = (_generate as any).default ?? _generate;

```

### NodePath.get() 的返回类型

```typescript
// path.get() 返回 NodePath | NodePath[]
// 当字段是数组时返回数组，需要用 Array.isArray 判断
const bodyPath = path.get("body");
if (Array.isArray(bodyPath)) {
  // bodyPath 是 NodePath[]
  bodyPath.forEach((p) => { /* ... */ });
} else {
  // bodyPath 是 NodePath
}

```

### cloneNode 用于避免节点共享问题

```typescript
// 同一个节点对象不能挂载在树的两处
// 错误写法：
const id = t.identifier("foo");
const decl = t.variableDeclaration("const", [
  t.variableDeclarator(id, null),
  t.variableDeclarator(id, null), // 共享 id，会报错
]);

// 正确写法：
const decl2 = t.variableDeclaration("const", [
  t.variableDeclarator(t.identifier("foo"), null),
  t.variableDeclarator(t.cloneNode(t.identifier("foo")), null),
]);

```

### replaceWith 后立即 skip()

```typescript
traverse(ast, {
  StringLiteral(path) {
    // 替换为新的 StringLiteral 会再次触发本 visitor，造成无限循环
    path.replaceWith(t.stringLiteral(path.node.value.trim()));
    path.skip(); // 跳过新节点的遍历，打破循环
  },
});

```

---

---

## 最佳实践

**使用 TypeScript 类型缩小节点类型**：在 `@babel/traverse` 的 Visitor 函数中，收到的 `path` 是联合类型；用类型守卫（`if (t.isIdentifier(path.node))`）缩小后，IDE 会自动补全节点的具体属性，避免手写字符串访问。

**用 `t.is*` 系列函数做运行时类型检查**：`t.isBinaryExpression(node)` 等函数比手动 `node.type === 'BinaryExpression'` 更安全——`@babel/types` 会处理别名（如 `t.isExpression` 匹配所有表达式类型），减少遗漏情况。

**构建节点时用 Builder 函数**：不要手写 `{ type: 'Identifier', name: 'x' }`，用 `t.identifier('x')` 让 Babel 自动填充所有必须字段（`extra`、位置信息等），避免缺少必须字段导致代码生成失败。

**TypeScript 项目中导入 `@babel/types` 的 `Node` 联合类型**：`import type { Node, Statement, Expression } from '@babel/types'` 为所有节点的联合类型，可以在自定义函数参数类型中使用，得到完整的类型推断。

**利用 `assertXxx` 系列做防御式编程**：`t.assertIdentifier(node)` 在节点类型不匹配时抛 `TypeError`，在调试阶段替代手动 `if (!t.isIdentifier(node)) throw new Error(...)` 更简洁；生产代码改用 `t.isIdentifier` 做条件分支。

---

## 常见陷阱

### 陷阱：`path.node` 类型太宽导致属性访问报 TypeScript 错误

**现象：** `path.node.name` 报 `Property 'name' does not exist on type 'Node'`。  
**原因：** `path.node` 是 `Node` 联合类型，只有 `Identifier` 有 `name` 属性；TypeScript 不知道当前是哪个具体类型。  
**解决：** 在 Visitor 中使用对应的 key（如 `Identifier(path) { ... }`），TypeScript 会自动推断 `path.node` 为 `Identifier` 类型；或用 `if (t.isIdentifier(path.node))` 类型守卫。

### 陷阱：`NodePath` 与 `Node` 混用导致错误

**现象：** 将 `path` 传入期望 `Node` 的函数，或将 `path.node` 传入期望 `NodePath` 的方法。  
**原因：** `NodePath` 包含 `node`（AST 节点）+ 作用域信息 + 父级引用等；它们是不同的对象，不可互换。  
**解决：** 规范命名：`path` 是 `NodePath`，`node` 是 `Node`；需要节点时用 `path.node`，需要路径操作（`replace`、`skip`）时用 `path`。

### 陷阱：`t.cloneNode` 浅拷贝共享子节点引用

**现象：** 修改克隆节点的子节点，原节点也被修改。  
**原因：** `t.cloneNode(node)` 默认浅拷贝，子节点还是同一引用；`t.cloneNode(node, true)` 才是深拷贝。  
**解决：** 需要独立副本时用 `t.cloneDeepWithoutLoc(node)` 或 `t.cloneNode(node, true)`（第二参数为 `true` 深拷贝）。

---

## 参见

[Babel AST入门](https://blog.vercanti.com/babel-ast-ru-men/)  
[js-ast-notes](https://blog.vercanti.com/javascript-ast-xue-xi-bi-ji/)  
[混淆还原](https://blog.vercanti.com/hun-yao-huan-yuan/)