Babel AST Utilities
Babel Types (`@babel/types`) is a foundational package within the Babel ecosystem, providing a comprehensive set of utility methods for creating, manipulating, and validating Abstract Syntax Tree (AST) nodes. It adheres to the ESTree specification and Babel's extended AST format, making it essential for anyone writing custom Babel plugins, codemods, or performing static analysis on JavaScript code. The current stable major version is `v7.x`, with the latest being `v7.29.2`, while `v8.x` is in release candidate phase. As part of the Babel monorepo, it follows Babel's frequent release cycle for patches and minors, with major versions introducing significant breaking changes. Its key differentiator is its tight integration and compatibility with Babel's parser (`@babel/parser`) and traverser (`@babel/traverse`), providing canonical builders (e.g., `t.identifier()`), type checkers (e.g., `t.isIdentifier()`), and assertion functions (e.g., `t.assertIdentifier()`) for programmatic AST interaction.
Common errors
-
TypeError: t.someBuilder is not a function
cause Attempting to use `babel-types` builder or checker methods after incorrectly importing the package, typically with a default import instead of a namespace import.fixUse a namespace import: `import * as t from '@babel/types';` if using ESM, or `const t = require('@babel/types');` if using CommonJS. -
Error: Unknown node type: 'MyCustomNode'
cause Attempting to create an AST node type (e.g., `t.myCustomNode()`) that is not a valid ESTree or Babel-specific AST node type, or is not supported by the specific Babel version being used.fixConsult the official `@babel/types` API documentation or ESTree specification to ensure all created node types are valid and supported. Ensure your Babel version is up-to-date if you are trying to use newer syntax features. -
Invariant Violation: someProperty must be a(n) string (or similar type mismatch)
cause Providing an argument of the wrong JavaScript type or an invalid value to a `babel-types` builder function, which expects specific types for its parameters (e.g., passing a number where a string is expected for an identifier name).fixReview the `@babel/types` API documentation for the specific builder function (`t.someBuilder(param1, param2...)`) to understand the expected types and structure of its arguments and adjust your code accordingly.
Warnings
- breaking Babel v8 has removed support for TypeScript's deprecated `module <identifier>` syntax (namespace imports) in `@babel/types` and related packages.
- breaking For Babel v8, `@babel/types` has removed legacy `.d.ts` files for TypeScript versions older than 4.0. Projects using older TypeScript versions will encounter type errors.
- gotcha Babel v8 is progressively removing deprecated default exports across its monorepo packages. While `@babel/types` primarily uses named exports (accessed via `import * as t from '@babel/types'`), users should be aware that other `@babel` packages may now strictly require named imports.
- gotcha Using a `@babel/types` version that is significantly different from other `@babel` core packages (like `@babel/parser`, `@babel/traverse`, or `@babel/generator`) can lead to AST incompatibility issues or unexpected behavior, as AST node definitions and structures evolve across Babel versions.
Install
-
npm install babel-types -
yarn add babel-types -
pnpm add babel-types
Imports
- t
import t from '@babel/types';
import * as t from '@babel/types';
- Node
import type { Node } from '@babel/types'; - ArrowFunctionExpression
import type { ArrowFunctionExpression } from '@babel/types';
Quickstart
import * as t from '@babel/types';
import generate from '@babel/generator';
// Create identifiers for 'a' and 'b'
const paramA = t.identifier('a');
const paramB = t.identifier('b');
// Create a binary expression 'a + b'
const sumExpression = t.binaryExpression('+', paramA, paramB);
// Create a return statement for 'a + b'
const returnStatement = t.returnStatement(sumExpression);
// Create a block statement for the function body
const functionBody = t.blockStatement([returnStatement]);
// Create an arrow function expression '(...params) => { ...body }'
const arrowFunction = t.arrowFunctionExpression(
[paramA, paramB], // params
functionBody, // body
false // async
);
// Create a variable declarator: 'add = (...)'
const declarator = t.variableDeclarator(t.identifier('add'), arrowFunction);
// Create a variable declaration: 'const add = (...)'
const variableDeclaration = t.variableDeclaration('const', [declarator]);
// Wrap the declaration in a Program node
const program = t.program([variableDeclaration]);
// Generate code from the AST (requires @babel/generator)
const { code } = generate(program);
console.log(code);
// Expected output: const add = (a, b) => a + b;