Babel Plugin Parameter Decorator
raw JSON → 1.0.16 verified Sat Apr 25 auth: no javascript
A Babel plugin that transforms function parameter decorators to behave like TypeScript parameter decorators. Current stable version is 1.0.16, with infrequent releases. It enables parameter decorators on constructor parameters and method parameters when using Babel with legacy decorator support. Unlike TypeScript's built-in support, this plugin requires the separate `@babel/plugin-proposal-decorators` with `legacy: true` and optionally `@babel/plugin-proposal-class-properties`. It is the only dedicated Babel plugin for parameter decorator transformation as of 2024, filling a gap left by other decorator plugins. Works with both JavaScript and TypeScript via Babel presets.
Common errors
error Error: [BABEL] unknown: Decorators are not enabled. ↓
cause Missing @babel/plugin-proposal-decorators plugin in Babel config.
fix
Add ["@babel/plugin-proposal-decorators", { "legacy": true }] before babel-plugin-parameter-decorator.
error TypeError: Cannot read properties of undefined (reading 'forEach') ↓
cause Parameter decorator used on a method without the companion method decorator (e.g., @validate) writing metadata.
fix
Ensure a method decorator writes the metadata that the parameter decorator expects; example uses @validate.
error Error: Parameter decorator is not a function ↓
cause Incorrect import or invalid decorator function; parameter decorator must return a function that takes (target, propertyKey, parameterIndex).
fix
Define parameter decorator correctly: function decorator(key) { return function(target, propKey, paramIndex) { ... }; }
Warnings
gotcha Plugin must be placed after @babel/plugin-proposal-decorators in plugins array. ↓
fix Ensure order: [['@babel/plugin-proposal-decorators', {legacy: true}], 'babel-plugin-parameter-decorator']
gotcha If using @babel/preset-typescript, TypeScript-only imports used in decorators will be removed by default, breaking references. ↓
fix Set 'onlyRemoveTypeImports' to true in preset options: ['@babel/preset-typescript', { onlyRemoveTypeImports: true }]
gotcha Requires @babel/plugin-proposal-decorators with legacy: true; the newer '2023-01' or '2023-11' decorator proposal is not supported. ↓
fix Use legacy: true (the Stage 1 decorators proposal).
Install
npm install babel-plugin-parameter-decorator yarn add babel-plugin-parameter-decorator pnpm add babel-plugin-parameter-decorator Imports
- babel-plugin-parameter-decorator wrong
{ "plugins": ["babel-plugin-parameter-decorator"] // missing @babel/plugin-proposal-decorators }correct// in .babelrc or babel.config.js { "plugins": [ ["@babel/plugin-proposal-decorators", { "legacy": true }], "babel-plugin-parameter-decorator" ] }
Quickstart
// Install dependencies
// npm install --save-dev @babel/core @babel/cli @babel/plugin-proposal-decorators babel-plugin-parameter-decorator
// .babelrc
{
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
"babel-plugin-parameter-decorator"
]
}
// input.js
function required(key) {
return function (target, propertyKey, parameterIndex) {
const metadata = `meta_${propertyKey}`;
target[metadata] = [
...(target[metadata] || []),
{ index: parameterIndex, key }
];
};
}
function validate(target, property, descriptor) {
const fn = descriptor.value;
descriptor.value = function(...args) {
const metadata = `meta_${property}`;
target[metadata].forEach(function(meta) {
if (args[meta.index] === undefined) {
throw new Error(`${meta.key} is required`);
}
});
return fn.apply(this, args);
};
return descriptor;
}
class Greeter {
constructor(message) {
this.greeting = message;
}
@validate
greet(@required('name') name) {
return "Hello " + name + ", " + this.greeting;
}
}
// Run: npx babel input.js --out-file output.js