@babel/plugin-transform-class-properties is a Babel plugin that transforms static class properties as well as properties declared with the property initializer syntax. It enables modern JavaScript class field syntax to work in older JavaScript environments that don't natively support class properties.
npm install --save-dev @babel/plugin-transform-class-propertiesThe plugin is typically used by string reference in Babel configuration rather than direct import:
// In babel.config.js or .babelrc
{
"plugins": ["@babel/plugin-transform-class-properties"]
}For programmatic usage (advanced):
const classPropertiesPlugin = require("@babel/plugin-transform-class-properties");// babel.config.js
module.exports = {
plugins: [
"@babel/plugin-transform-class-properties"
]
};
// With options
module.exports = {
plugins: [
["@babel/plugin-transform-class-properties", { loose: true }]
]
};Transform Example:
Input:
class MyClass {
static staticProperty = "static value";
instanceProperty = "instance value";
constructor() {
this.otherProperty = "other";
}
}Output (non-loose mode):
var MyClass = /*#__PURE__*/babelHelpers.createClass(function MyClass() {
"use strict";
babelHelpers.classCallCheck(this, MyClass);
babelHelpers.defineProperty(this, "instanceProperty", "instance value");
this.otherProperty = "other";
});
babelHelpers.defineProperty(MyClass, "staticProperty", "static value");The main export is a Babel plugin factory function that creates a plugin configuration.
/**
* Default export is a Babel plugin created using the declare helper
* The plugin transforms class properties syntax for older JavaScript environments
* @param api - Babel plugin API object with version assertion
* @param options - Plugin configuration options
* @returns Babel plugin object with class property transformation logic
*/
declare const classPropertiesPlugin: (
api: PluginAPI,
options?: Options
) => PluginObject;
export default classPropertiesPlugin;
export interface Options {
/** Enable loose mode transformation for better performance and compatibility */
loose?: boolean;
}The Options interface (shown above) configures the transformation behavior:
Loose Mode Behavior:
With loose: true, the transform generates simpler assignment statements:
// Input
class MyClass {
instanceProperty = "value";
}
// Output (loose: true)
var MyClass = /*#__PURE__*/babelHelpers.createClass(function MyClass() {
"use strict";
babelHelpers.classCallCheck(this, MyClass);
this.instanceProperty = "value";
});
// Output (loose: false, default)
var MyClass = /*#__PURE__*/babelHelpers.createClass(function MyClass() {
"use strict";
babelHelpers.classCallCheck(this, MyClass);
babelHelpers.defineProperty(this, "instanceProperty", "value");
});The plugin uses standard Babel types from @babel/core:
interface PluginAPI {
/** Assert that the Babel version meets minimum requirements */
assertVersion(version: number | string): void;
}
interface PluginObject {
/** Plugin name for debugging and identification */
name: string;
/** Function to manipulate parser options */
manipulateOptions?: (opts: any, parserOpts: any) => void;
/** Visitor pattern object for AST transformation */
visitor?: Visitor;
}
interface Visitor {
/** Methods for visiting different AST node types during transformation */
[key: string]: VisitorFunction | VisitorObject;
}
interface VisitorFunction {
(path: NodePath, state: any): void;
}
interface VisitorObject {
enter?: VisitorFunction;
exit?: VisitorFunction;
}
interface NodePath {
/** The current AST node being visited */
node: any;
/** Parent node path */
parent: NodePath;
/** Get parent node by type */
findParent(callback: (path: NodePath) => boolean): NodePath | null;
/** Replace current node */
replaceWith(node: any): void;
/** Remove current node */
remove(): void;
}The plugin transforms several types of class property declarations:
Static Properties
class MyClass {
static count = 0;
static config = { debug: true };
}Instance Properties with Initializers
class MyClass {
name = "default";
items = [];
handler = () => {};
}Private Properties (with WeakMap transformation)
// Input
class MyClass {
#privateField = "private";
static #staticPrivate = "static private";
}
// Output (non-loose mode)
var _privateField = /*#__PURE__*/new WeakMap();
var _staticPrivate = {
writable: true,
value: "static private"
};
var MyClass = /*#__PURE__*/babelHelpers.createClass(function MyClass() {
"use strict";
babelHelpers.classCallCheck(this, MyClass);
babelHelpers.classPrivateFieldInitSpec(this, _privateField, "private");
});
babelHelpers.classStaticPrivateFieldSpecSet(MyClass, MyClass, _staticPrivate, "static private");The plugin automatically registers necessary parser plugins to recognize class property syntax:
"classProperties" - Enables parsing of public class properties"classPrivateProperties" - Enables parsing of private class properties (Babel 7)The plugin requires Babel 7.x and automatically validates version compatibility using the REQUIRED_VERSION function:
/** Global function for Babel version assertion */
declare function REQUIRED_VERSION(version: number): number | string;
declare function REQUIRED_VERSION(version: string): string;The plugin uses feature flags from the helper library to enable specific transformations:
/** Feature constants for class transformation capabilities */
const FEATURES = Object.freeze({
fields: 1 << 1,
privateMethods: 1 << 2,
decorators: 1 << 3,
privateIn: 1 << 4,
staticBlocks: 1 << 5,
});Common configuration patterns for different build setups:
Standard Configuration:
// babel.config.js
module.exports = {
presets: ["@babel/preset-env"],
plugins: ["@babel/plugin-transform-class-properties"]
};With TypeScript:
// babel.config.js
module.exports = {
presets: [
"@babel/preset-env",
"@babel/preset-typescript"
],
plugins: [
["@babel/plugin-transform-class-properties", { loose: true }]
]
};// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(js|ts)$/,
use: {
loader: 'babel-loader',
options: {
plugins: ['@babel/plugin-transform-class-properties']
}
}
}
]
}
};The plugin will throw compilation errors for:
Common error scenarios and resolutions: