Transforms ES2019 optional catch binding syntax into ES5-compatible code by automatically adding unused parameter names to catch clauses
npx @tessl/cli install tessl/npm--babel--plugin-transform-optional-catch-binding@7.27.0Transforms ES2019 optional catch binding syntax into ES5-compatible code by automatically adding unused parameter names to catch clauses that omit the error parameter.
npm install --save-dev @babel/plugin-transform-optional-catch-binding// As Babel plugin configuration
module.exports = {
plugins: ["@babel/plugin-transform-optional-catch-binding"]
};For programmatic usage:
import plugin from "@babel/plugin-transform-optional-catch-binding";CommonJS:
const plugin = require("@babel/plugin-transform-optional-catch-binding");Module Structure:
./lib/index.js (compiled from TypeScript)./lib/index.d.tsAdd to your Babel configuration to automatically transform optional catch bindings:
// babel.config.js
module.exports = {
plugins: ["@babel/plugin-transform-optional-catch-binding"]
};Input code (ES2019 optional catch binding):
try {
riskyOperation();
} catch {
console.log("Something went wrong, but we don't need the error details");
}Output code (ES5-compatible):
try {
riskyOperation();
} catch (_unused) {
console.log("Something went wrong, but we don't need the error details");
}The main export is a Babel plugin factory function that creates a transformation plugin using the declare helper from @babel/helper-plugin-utils.
/**
* Creates a Babel plugin for transforming optional catch bindings
* @param api - Babel API object providing transformation utilities
* @returns Babel plugin configuration object
*/
function plugin(api: PluginAPI): PluginObject;
/**
* Declare function from @babel/helper-plugin-utils that wraps plugin creation
* @param builder - Function that builds the plugin object
* @returns Plugin factory function
*/
function declare<State = object, Option = object>(
builder: (api: PluginAPI, options: Option, dirname: string) => PluginObject<State & PluginPass>
): (api: PluginAPI, options: Option, dirname: string) => PluginObject<State & PluginPass>;
/**
* Global function for Babel version requirements checking
* @param version - Major version number (e.g., 7) or version string
* @returns Version range string for assertVersion
*/
function REQUIRED_VERSION(version: number): number | string;
function REQUIRED_VERSION(version: string): string;
interface PluginAPI {
/** Check that Babel version meets requirements */
assertVersion(range: number | string): void;
/** Current Babel version */
version: string;
}
interface PluginObject {
/** Plugin identifier name */
name: "transform-optional-catch-binding";
/** Parser plugin configuration function */
manipulateOptions?: (opts: any, parser: ParserOptions) => void;
/** AST visitor configuration */
visitor: {
CatchClause(path: NodePath<CatchClause>): void;
};
}
interface ParserOptions {
/** Array of parser plugins to enable */
plugins: string[];
}
interface NodePath<T = any> {
/** AST node being visited */
node: T;
/** Scope information for the node */
scope: Scope;
/** Get child path by property name */
get(property: string): NodePath;
/** Replace this node with a new node */
replaceWith(replacement: any): void;
/** Replace this path with multiple nodes */
replaceWithMultiple(nodes: any[]): void;
/** Remove this node from the AST */
remove(): void;
/** Insert nodes before this node */
insertBefore(nodes: any | any[]): void;
/** Insert nodes after this node */
insertAfter(nodes: any | any[]): void;
/** Skip transformation of this node's children */
skip(): void;
/** Stop traversal entirely */
stop(): void;
}
interface CatchClause {
/** Node type identifier */
type: "CatchClause";
/** Error parameter identifier (may be null for optional catch) */
param: Identifier | null;
/** The catch block body */
body: BlockStatement;
}
interface BlockStatement {
/** Node type identifier */
type: "BlockStatement";
/** Array of statements in the block */
body: Statement[];
}
interface Statement {
/** Node type identifier */
type: string;
}
interface Scope {
/** Generate a unique identifier within this scope */
generateUidIdentifier(name: string): Identifier;
}
interface Identifier {
/** Node type identifier */
type: "Identifier";
/** Identifier name */
name: string;
}
interface PluginPass {
/** Current file information */
file: any;
/** Plugin options */
opts: any;
}Automatically configures the Babel parser to recognize optional catch binding syntax. This is only needed in non-Babel 8 environments where the optionalCatchBinding parser plugin must be manually enabled.
/**
* Configures parser options to enable optional catch binding syntax
* @param opts - Babel options (unused by this plugin)
* @param parser - Parser configuration object
*/
manipulateOptions(opts: any, parser: ParserOptions): void;
/**
* The manipulateOptions function is conditionally defined based on environment:
* - In Babel 8: undefined (parser plugin enabled by default)
* - In Babel 7: adds "optionalCatchBinding" to parser.plugins
*/Transforms catch clauses that lack error parameters by adding generated unused identifiers.
/**
* Visits CatchClause AST nodes and transforms optional catch bindings
* @param path - NodePath for the catch clause being processed
*/
CatchClause(path: NodePath<CatchClause>): void;Transformation logic:
path.node.param is null (indicating optional catch binding)path.scope.generateUidIdentifier("unused")path.get("param")paramPath.replaceWith(uid)Implementation details:
CatchClause(path) {
if (!path.node.param) {
const uid = path.scope.generateUidIdentifier("unused");
const paramPath = path.get("param");
paramPath.replaceWith(uid);
}
}// babel.config.js
module.exports = {
presets: ["@babel/preset-env"],
plugins: ["@babel/plugin-transform-optional-catch-binding"]
};import { transform } from "@babel/core";
import plugin from "@babel/plugin-transform-optional-catch-binding";
const code = `
try {
throw new Error("test");
} catch {
console.log("caught error");
}
`;
const result = transform(code, {
plugins: [plugin]
});
console.log(result.code);
// Output: try { throw new Error("test"); } catch (_unused) { console.log("caught error"); }// Input
try {
operation1();
} catch {
console.log("operation1 failed");
}
try {
operation2();
} catch {
console.log("operation2 failed");
}
// Output (each gets a unique identifier)
try {
operation1();
} catch (_unused) {
console.log("operation1 failed");
}
try {
operation2();
} catch (_unused2) {
console.log("operation2 failed");
}The plugin will throw an error if used with an incompatible Babel version:
Error: Requires Babel "^7.0.0-beta.41", but was loaded with "6.x.x"This validation occurs during plugin initialization via api.assertVersion(REQUIRED_VERSION(7)).