@babel/plugin-transform-destructuring is a Babel plugin that compiles ES2015 (ES6) destructuring syntax to ES5-compatible code. It transforms array destructuring, object destructuring, destructuring in function parameters, catch clauses, and for-in/for-of loops. The plugin handles complex patterns including nested destructuring, default values, and rest patterns while preserving the semantic behavior of destructuring operations.
npm install --save-dev @babel/plugin-transform-destructuringimport transformDestructuring from "@babel/plugin-transform-destructuring";
import {
Options,
buildObjectExcludingKeys,
unshiftForXStatementBody
} from "@babel/plugin-transform-destructuring";For CommonJS:
const transformDestructuring = require("@babel/plugin-transform-destructuring");
const { buildObjectExcludingKeys, unshiftForXStatementBody } = require("@babel/plugin-transform-destructuring");// babel.config.js
module.exports = {
plugins: [
["@babel/plugin-transform-destructuring", {
allowArrayLike: false,
loose: false,
useBuiltIns: false
}]
]
};// Input code (ES2015+ destructuring)
const { name, age } = user;
const [first, second, ...rest] = items;
function greet({ name = "World" }) {
console.log(`Hello, ${name}!`);
}
// Output after transformation (ES5 compatible)
const name = user.name, age = user.age;
const first = items[0], second = items[1], rest = items.slice(2);
function greet(_ref) {
const name = _ref.name === void 0 ? "World" : _ref.name;
console.log("Hello, " + name + "!");
}The plugin is built around several key components:
declare() from @babel/helper-plugin-utilsMain plugin export that integrates with Babel's transformation pipeline.
/**
* Main Babel plugin export for destructuring transformation
* @param api - Babel API object with version checking and assumptions
* @param options - Plugin configuration options
* @returns Babel plugin object with visitor methods
*/
declare function transformDestructuring(api: any, options: Options): {
name: string;
visitor: PluginVisitor;
};
export default transformDestructuring;
interface Options {
/** Enable transformation of array-like objects (e.g., arguments, NodeList) */
allowArrayLike?: boolean;
/** Enable loose mode transformations for better performance */
loose?: boolean;
/** Use built-in methods when available instead of helper functions */
useBuiltIns?: boolean;
}
interface PluginVisitor {
ExportNamedDeclaration(path: NodePath): void;
ForXStatement(path: NodePath<ForXStatement>): void;
CatchClause(path: NodePath): void;
AssignmentExpression(path: NodePath, state: any): void;
VariableDeclaration(path: NodePath, state: any): void;
}Core transformation engine for converting destructuring patterns to sequential assignments.
/**
* Main class for transforming destructuring patterns into sequential assignments
*/
export class DestructuringTransformer {
arrayRefSet: Set<string>;
constructor(opts: DestructuringTransformerOption);
/**
* Initialize destructuring transformation for a given pattern and reference
* @param pattern - The destructuring pattern (ArrayPattern, ObjectPattern, etc.)
* @param ref - The expression being destructured
*/
init(pattern: LVal, ref: Expression): void;
/**
* Add a destructuring assignment to the transformation
* @param id - The target identifier or pattern
* @param init - The initialization expression
*/
push(id: LVal | PatternLike, init: Expression | null): void;
/**
* Convert an expression to an array for array destructuring
* @param node - The expression to convert
* @param count - Optional specific number of elements needed
* @returns Expression that evaluates to an array
*/
toArray(node: Expression, count?: false | number): Expression;
/**
* Build a variable assignment statement
* @param id - The assignment target
* @param init - The initialization expression
* @returns Variable assignment node
*/
buildVariableAssignment(
id: AssignmentExpression["left"],
init: Expression
): ExpressionStatement | VariableDeclaration;
/**
* Build a variable declaration statement
* @param id - The identifier being declared
* @param init - The initialization expression
* @returns Variable declaration node
*/
buildVariableDeclaration(id: Identifier, init: Expression): VariableDeclaration;
/**
* Returns the appropriate extends helper (Object.assign or helper function)
* @returns Member expression or helper call
*/
getExtendsHelper(): MemberExpression | CallExpression;
}
interface DestructuringTransformerOption {
/** Block hoisting priority for generated nodes */
blockHoist?: number;
/** Assignment operator for generated assignments */
operator?: AssignmentExpression["operator"];
/** Array to collect generated transformation nodes */
nodes?: DestructuringTransformerNode[];
/** Variable declaration kind (var, let, const) */
kind?: VariableDeclarationKindAllowsPattern;
/** Babel scope object for identifier generation and binding management (required) */
scope: Scope;
/** Whether array-like objects should be treated as iterable (required) */
arrayLikeIsIterable: boolean;
/** Whether iterables should be assumed to be arrays for optimization (required) */
iterableIsArray: boolean;
/** Whether object rest should exclude symbol properties (required) */
objectRestNoSymbols: boolean;
/** Whether to use built-in methods instead of helper functions (required) */
useBuiltIns: boolean;
/** Function to register Babel helper functions (required) */
addHelper: File["addHelper"];
}Helper functions for specific destructuring transformations.
/**
* Build an object excluding specified keys (used for object rest patterns)
* @param excludedKeys - Array of properties to exclude
* @param objRef - Reference to the source object
* @param scope - Babel scope object
* @param addHelper - Helper function registration
* @param objectRestNoSymbols - Whether to exclude symbol properties
* @param useBuiltIns - Whether to use built-in Object.assign
* @returns Call expression creating the filtered object
*/
export function buildObjectExcludingKeys<T extends ExcludingKey>(
excludedKeys: T[],
objRef: Expression,
scope: Scope,
addHelper: File["addHelper"],
objectRestNoSymbols: boolean,
useBuiltIns: boolean
): CallExpression;
/**
* Convert a variable declaration containing destructuring patterns
* @param path - NodePath for the variable declaration
* @param addHelper - Helper function registration
* @param arrayLikeIsIterable - Array-like transformation assumption
* @param iterableIsArray - Iterable transformation assumption
* @param objectRestNoSymbols - Object rest symbol handling assumption
* @param useBuiltIns - Whether to use built-in methods
*/
export function convertVariableDeclaration(
path: NodePath<VariableDeclaration>,
addHelper: File["addHelper"],
arrayLikeIsIterable: boolean,
iterableIsArray: boolean,
objectRestNoSymbols: boolean,
useBuiltIns: boolean
): void;
/**
* Convert an assignment expression containing destructuring patterns
* @param path - NodePath for the assignment expression
* @param addHelper - Helper function registration
* @param arrayLikeIsIterable - Array-like transformation assumption
* @param iterableIsArray - Iterable transformation assumption
* @param objectRestNoSymbols - Object rest symbol handling assumption
* @param useBuiltIns - Whether to use built-in methods
*/
export function convertAssignmentExpression(
path: NodePath<AssignmentExpression & { left: Pattern }>,
addHelper: File["addHelper"],
arrayLikeIsIterable: boolean,
iterableIsArray: boolean,
objectRestNoSymbols: boolean,
useBuiltIns: boolean
): void;
/**
* Insert statements at the beginning of a for-X statement body
* @param statementPath - NodePath for the ForXStatement
* @param newStatements - Array of statements to insert
*/
export function unshiftForXStatementBody(
statementPath: NodePath<ForXStatement>,
newStatements: Statement[]
): void;/** Union type for nodes generated by the destructuring transformer */
export type DestructuringTransformerNode =
| VariableDeclaration
| ExpressionStatement
| ReturnStatement;
/** Variable declaration kinds that support destructuring patterns */
export type VariableDeclarationKindAllowsPattern = Exclude<
VariableDeclaration["kind"],
"using" | "await using"
>;
/** Interface for objects with excludable keys used in object rest patterns */
interface ExcludingKey {
key: Expression | PrivateName;
computed: boolean;
}
/** Babel AST types used by the plugin */
interface LVal {} // From @babel/types
interface Pattern {} // From @babel/types
interface PatternLike {} // From @babel/types
interface Expression {} // From @babel/types
interface Statement {} // From @babel/types
interface Identifier {} // From @babel/types
interface VariableDeclaration {} // From @babel/types
interface AssignmentExpression {} // From @babel/types
interface CallExpression {} // From @babel/types
interface MemberExpression {} // From @babel/types
interface ExpressionStatement {} // From @babel/types
interface ReturnStatement {} // From @babel/types
interface PrivateName {} // From @babel/types
interface ForXStatement {} // From @babel/types
interface NodePath<T = any> {} // From @babel/traverse
interface Scope {} // From @babel/traverse
interface File {} // From @babel/coreThe plugin handles destructuring in the following contexts:
const { x, y } = obj; → const x = obj.x, y = obj.y;({ x, y } = obj); → x = obj.x, y = obj.y;function f({ x }) {} → function f(_ref) { const x = _ref.x; }for (const { x } of arr) {} → for (const _ref of arr) { const x = _ref.x; }catch ({ message }) {} → catch (_ref) { const message = _ref.message; }export const { x } = obj; → Split into separate export and declarationSupports all ES2015+ destructuring patterns:
{ prop, nested: { deep } }[first, second, ...rest]{ prop = defaultValue }{ ...rest } and [...rest]{ obj: { nested } } and [[nested]]The plugin handles various edge cases:
undefined