JavaScript syntax tree transformer, nondestructive pretty-printer, and automatic source map generator
Recast is a JavaScript syntax tree transformer that parses code into an Abstract Syntax Tree (AST), allows programmatic modifications, and reprints it back to source code while preserving the original formatting. Unlike traditional pretty-printers that reformat entire files, Recast only reprints the portions of code you've actually modified, leaving unchanged code exactly as the developer originally wrote it.
The library solves a critical problem in automated refactoring: maintaining code style and formatting during large-scale transformations. When you need to rename thousands of function calls, modernize syntax patterns, or apply complex refactoring across a codebase, manual editing becomes impractical. Recast enables these transformations programmatically while respecting existing code conventions, preserving comments, and maintaining git diff readability.
With over 19 million weekly downloads, Recast powers numerous developer tools including code migration utilities, linters, bundlers, and automated refactoring systems. It's built on a compatible parser interface similar to esprima, supports multiple JavaScript parsers (including Babel and Acorn), and generates source maps automatically. The library is particularly valuable for teams maintaining large codebases who need to apply systematic changes without disrupting established formatting conventions.
Recast achieves formatting preservation through a shadow AST mechanism: it maintains references to original nodes via an .original property, allowing it to detect which nodes were modified during traversal. Only modified subtrees get reprinted using the library's pretty-printer, while unmodified nodes retain their original source representation character-for-character.
const recast = require('recast');
const { namedTypes: n, builders: b } = recast.types;
const sourceCode = `
function calculatePrice(items) {
var total = 0;
for (var i = 0; i < items.length; i++) {
total += items[i].price;
}
return total;
}
`;
// Parse code into AST
const ast = recast.parse(sourceCode);
// Transform var declarations to const/let
recast.visit(ast, {
visitVariableDeclaration(path) {
const node = path.node;
if (node.kind === 'var') {
// Check if variable is reassigned
const isReassigned = path.scope.lookup(node.declarations[0].id.name)
?.getBindings()[node.declarations[0].id.name]
?.some(binding => binding.parentPath.value.type === 'AssignmentExpression');
node.kind = isReassigned ? 'let' : 'const';
}
this.traverse(path);
},
// Transform for loop to forEach
visitForStatement(path) {
const node = path.node;
// Simple pattern match for array iteration
if (n.MemberExpression.check(node.test?.right) &&
node.test.right.property.name === 'length') {
const arrayName = node.test.right.object.name;
const body = node.body.body;
// Create forEach call
const forEachCall = b.expressionStatement(
b.callExpression(
b.memberExpression(
b.identifier(arrayName),
b.identifier('forEach'),
false
),
[b.arrowFunctionExpression(
[b.identifier('item')],
b.blockStatement(body)
)]
)
);
path.replace(forEachCall);
}
return false;
}
});
// Print only modified code, preserving original formatting elsewhere
const transformedCode = recast.print(ast, { tabWidth: 2 }).code;
console.log(transformedCode);
// Output maintains original structure but with modernized syntaxLarge-scale codebase refactoring: When migrating from CommonJS to ES modules across hundreds of files, Recast can automatically transform require() calls to import statements while preserving each file's unique formatting style, comment placement, and whitespace conventions.
API migration automation: When a library releases a breaking version with renamed methods, Recast enables writing a codemod script that finds all usages of old API calls and transforms them to the new syntax, making upgrades across large projects manageable without manual find-and-replace.
Code modernization tooling: Building tools that upgrade legacy code patterns (converting var to const/let, transforming callbacks to async/await, updating deprecated syntax) while maintaining the developer's original code style and avoiding unnecessary diffs in version control.
Custom linting with auto-fix: Creating specialized lint rules that not only detect issues but automatically fix them by modifying the AST, such as enforcing consistent error handling patterns or standardizing import ordering across a monorepo.
Template-based code generation: Generating boilerplate code from templates or schemas where you parse existing code files, inject new function definitions or class methods, and write back the modified file without reformatting the entire document.
npm install recastpnpm add recastbun add recast