{"id":12836,"library":"ast-types","title":"Abstract Syntax Tree (AST) Types and Builders","description":"ast-types is a foundational JavaScript library that provides an Esprima-compatible implementation of the Mozilla JavaScript Parser API, specifically designed for working with Abstract Syntax Trees (ASTs). It offers a robust and modular type hierarchy for representing JavaScript code as a tree structure, enabling efficient analysis, transformation, and code generation. The current stable version is `0.14.2`. While widely adopted as a dependency in many JavaScript tooling projects (e.g., Recast, Babel), it maintains a very slow release cadence, suggesting a mature and largely feature-complete state. Key differentiators include its `namedTypes` object for type-safe AST node inspection, `builders` for programmatic AST construction, and a powerful `visit` abstraction for tree traversal and modification. It provides a low-level, high-performance API for direct AST manipulation, often used in transpilers, linters, and code formatters.","status":"active","version":"0.14.2","language":"javascript","source_language":"en","source_url":"git://github.com/benjamn/ast-types","tags":["javascript","ast","abstract syntax tree","hierarchy","mozilla","spidermonkey","parser api","esprima","types","typescript"],"install":[{"cmd":"npm install ast-types","lang":"bash","label":"npm"},{"cmd":"yarn add ast-types","lang":"bash","label":"yarn"},{"cmd":"pnpm add ast-types","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"ESM named import is preferred for `namedTypes` aliased as `n`. While CommonJS `require` works, ESM is recommended for modern Node.js environments.","wrong":"const n = require('ast-types').namedTypes;","symbol":"namedTypes","correct":"import { namedTypes as n } from 'ast-types';"},{"note":"ESM named import is preferred for `builders` aliased as `b`. `builders` are essential for creating new AST nodes programmatically.","wrong":"const b = require('ast-types').builders;","symbol":"builders","correct":"import { builders as b } from 'ast-types';"},{"note":"The `visit` function is the primary mechanism for traversing an AST. It is a named export.","wrong":"const visit = require('ast-types').visit;","symbol":"visit","correct":"import { visit } from 'ast-types';"}],"quickstart":{"code":"import { parse, visit, namedTypes as n, builders as b } from 'ast-types';\nimport { print } from 'recast'; // recast is commonly used with ast-types for printing modified ASTs\n\nconst code = `\nfunction greet(name) {\n  let message = 'Hello, ' + name + '!';\n  return message;\n}\n`;\n\n// Parse the code into an AST\nconst ast = parse(code);\n\n// Traverse the AST to find and modify a variable declaration\nvisit(ast, {\n  visitVariableDeclarator(path) {\n    const node = path.node;\n    if (n.Identifier.check(node.id) && node.id.name === 'message') {\n      // Change the variable name from 'message' to 'greeting'\n      node.id = b.identifier('greeting');\n\n      // Modify the init expression to include a different greeting\n      // Find the BinaryExpression 'Hello, ' + name + '!'\n      if (n.BinaryExpression.check(node.init)) {\n        // Replace 'Hello, ' with 'Greetings, '\n        if (n.BinaryExpression.check(node.init.left) && n.Literal.check(node.init.left.left)) {\n          node.init.left.left.value = 'Greetings, ';\n        }\n      }\n    }\n    this.traverse(path); // Continue traversing children\n  },\n\n  visitReturnStatement(path) {\n    const node = path.node;\n    // Update the returned identifier if it was 'message'\n    if (n.Identifier.check(node.argument) && node.argument.name === 'message') {\n      node.argument.name = 'greeting';\n    }\n    this.traverse(path); // Continue traversing children\n  }\n});\n\n// Print the modified AST back to code\nconst modifiedCode = print(ast).code;\nconsole.log(modifiedCode);\n/* Expected Output:\nfunction greet(name) {\n  let greeting = 'Greetings, ' + name + '!';\n  return greeting;\n}\n*/","lang":"typescript","description":"This quickstart demonstrates parsing JavaScript code into an AST, then using `ast-types`'s `visit` function to traverse the tree. It modifies a variable declarator's identifier and its initializer's literal value, and updates a return statement's argument, finally printing the transformed code."},"warnings":[{"fix":"Carefully review the documentation for `NodePath` methods. For complex modifications, consider creating new nodes with `builders` and using `path.replace()` to swap out subtrees, or building a new AST from scratch. Always test transformations thoroughly.","message":"When modifying the AST during traversal, ensure you understand how `path.replace()` and `path.prune()` affect the tree. Incorrect usage, especially with `prune()`, can lead to unexpected tree structures or omitted nodes. `path.prune()` removes the current node and prevents its children from being visited, effectively stopping traversal down that branch.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Ensure that the parser you use (e.g., `Esprima`, `Babylon`/`@babel/parser`, `meriyah`) is up-to-date and generates ASTs compatible with the ESTree specification that `ast-types` expects. If working with very new JS features, you might need to combine `ast-types` with a more frequently updated parser and potentially `recast` to handle new node types gracefully.","message":"`ast-types` has a very slow release cadence, with the latest version `0.14.2` published over six years ago (as of 2026). While stable, this means it may not immediately support the newest ECMAScript syntax features without a compatible parser (like Babel's parser or `meriyah` with proper configuration) providing the AST first.","severity":"gotcha","affected_versions":"<=0.14.2"},{"fix":"For optimal compatibility in TypeScript projects, set `\"esModuleInterop\": true` and `\"moduleResolution\": \"Bundler\"` (or `\"NodeNext\"`) in your `tsconfig.json`. When importing CommonJS modules into ESM, you may need `import * as pkg from 'pkg';` or dynamic `await import('pkg');` if default exports are not handled implicitly.","message":"While `ast-types` ships with TypeScript types, incorrect configuration of `esModuleInterop` or `allowSyntheticDefaultImports` in `tsconfig.json` can lead to issues with `import` statements, particularly in mixed CommonJS/ESM environments.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure the input code is valid and that the parser function (e.g., `parse` from `recast` or a direct parser like `esprima`) executed successfully and returned a valid AST object before attempting to access its properties.","cause":"Attempting to traverse or manipulate an AST that was not correctly parsed or is empty.","error":"TypeError: Cannot read properties of undefined (reading 'body')"},{"fix":"If the type is a standard ESTree node, ensure your `ast-types` version supports it. If it's a custom or non-standard node, you may need to define it using `types.def('MyCustomNode', { ... });` before trying to use it with builders or traversal.","cause":"You are attempting to create an AST node type (or a builder is attempting to create one) that `ast-types` does not recognize or has not been explicitly defined in its type hierarchy. This often happens with custom AST extensions or if the parser produces non-standard nodes.","error":"Error: Unknown type X. Please define it using types.def(...);"}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null}