@babel/plugin-transform-duplicate-keys is a Babel transformation plugin that compiles JavaScript objects with duplicate keys to valid ES5 strict mode. It detects duplicate property names and converts them to computed property syntax to ensure ES5 compliance.
npm install --save-dev @babel/plugin-transform-duplicate-keys// CommonJS
const duplicateKeysPlugin = require("@babel/plugin-transform-duplicate-keys");// ES Module
import duplicateKeysPlugin from "@babel/plugin-transform-duplicate-keys";// babel.config.js
module.exports = {
plugins: ["@babel/plugin-transform-duplicate-keys"]
};import { transform } from "@babel/core";
import duplicateKeysPlugin from "@babel/plugin-transform-duplicate-keys";
const result = transform(sourceCode, {
plugins: [duplicateKeysPlugin]
});Input:
var obj = {
a: 1,
get a() { return 2; },
a: 3
};Output:
var obj = {
a: 1,
get ["a"]() { return 2; },
["a"]: 3
};The main plugin export is a Babel plugin factory function created using declare() from @babel/helper-plugin-utils.
/**
* Creates a Babel plugin for transforming duplicate object keys
* @param api - Babel plugin API object with version assertion and utilities
* @returns Plugin configuration object with visitor pattern
*/
function duplicateKeysPlugin(api: PluginApi): PluginObject;
/**
* Plugin API provided by Babel to plugin factory functions
*/
interface PluginApi {
/** Assert required Babel version (e.g., api.assertVersion(7) for Babel 7.x) */
assertVersion(version: number): void;
/** Babel types utilities for AST node creation and testing */
types: typeof import("@babel/types");
}
/**
* Plugin configuration object returned by plugin factory
*/
interface PluginObject {
/** Plugin identifier used by Babel */
name: "transform-duplicate-keys";
/** Visitor pattern object for AST traversal */
visitor: VisitorMap;
}
/**
* Visitor map defining which AST nodes to transform
*/
interface VisitorMap {
/** Transforms object expressions containing duplicate keys */
ObjectExpression(path: NodePath<ObjectExpression>): void;
}The plugin transforms objects by identifying duplicate keys and converting duplicates to computed property syntax:
The transformation ensures objects comply with ES5 strict mode duplicate key restrictions:
The plugin is created using the declare() function from @babel/helper-plugin-utils:
/**
* Plugin creation using Babel's helper utilities
* @param callback - Function that receives plugin API and returns plugin configuration
* @returns Babel plugin function ready for use in configuration
*/
declare(callback: (api: PluginApi) => PluginObject): BabelPlugin;
/**
* Standard Babel plugin function type
*/
type BabelPlugin = (api: PluginApi) => PluginObject;api.assertVersion(7))@babel/helper-plugin-utils for plugin creation utilities@babel/core for AST types and transformation APIs/**
* Babel NodePath interface for traversing and manipulating AST nodes
*/
interface NodePath<T> {
/** The actual AST node being traversed */
node: T;
/** Parent path in the AST */
parent: NodePath<any>;
/** Hub instance for plugin context */
hub: Hub;
/** Additional methods for node manipulation (simplified) */
}
/**
* Babel AST node representing object literal expressions
*/
interface ObjectExpression {
type: "ObjectExpression";
/** Array of object properties, methods, and spread elements */
properties: Array<ObjectProperty | ObjectMethod | SpreadElement>;
}
/**
* Babel AST node for object property definitions
*/
interface ObjectProperty {
type: "ObjectProperty";
/** Property key (identifier, string literal, or numeric literal) */
key: Identifier | StringLiteral | NumericLiteral | BigIntLiteral;
/** Property value expression */
value: Expression;
/** Whether the property uses computed syntax ([key]: value) */
computed: boolean;
/** Whether property is shorthand (ES6 shorthand syntax) */
shorthand: boolean;
}
/**
* Babel AST node for object method definitions (getters, setters, methods)
*/
interface ObjectMethod {
type: "ObjectMethod";
/** Method key (identifier, string literal, or numeric literal) */
key: Identifier | StringLiteral | NumericLiteral | BigIntLiteral;
/** Method kind: regular method, getter, or setter */
kind: "method" | "get" | "set";
/** Whether the method uses computed syntax */
computed: boolean;
/** Method parameters */
params: Array<Identifier>;
/** Method body */
body: BlockStatement;
}
/**
* Babel AST node for spread elements in objects (...obj)
*/
interface SpreadElement {
type: "SpreadElement";
/** Expression being spread */
argument: Expression;
}
/**
* Babel AST node for identifier names
*/
interface Identifier {
type: "Identifier";
/** The identifier name */
name: string;
}
/**
* Babel AST node for string literals
*/
interface StringLiteral {
type: "StringLiteral";
/** The string value */
value: string;
}
/**
* Babel AST node for numeric literals
*/
interface NumericLiteral {
type: "NumericLiteral";
/** The numeric value */
value: number;
}
/**
* Babel AST node for big integer literals
*/
interface BigIntLiteral {
type: "BigIntLiteral";
/** The big integer value as string */
value: string;
}
/**
* Union type for all possible expressions in Babel AST
*/
type Expression =
| Identifier
| StringLiteral
| NumericLiteral
| BigIntLiteral
| ObjectExpression
// ... other expression types
/**
* Babel AST node for block statements (method bodies)
*/
interface BlockStatement {
type: "BlockStatement";
/** Array of statements in the block */
body: Array<Statement>;
}
/**
* Union type for all possible statements in Babel AST
*/
type Statement = any; // Simplified for this context