or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

@babel/plugin-transform-classes

@babel/plugin-transform-classes is a Babel transform plugin that compiles ES2015/ES6 class declarations and expressions into ES5-compatible JavaScript code. It handles class inheritance, method definitions, static methods, and constructor functions, making modern JavaScript classes compatible with older environments.

Package Information

  • Package Name: @babel/plugin-transform-classes
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install --save-dev @babel/plugin-transform-classes

Core Imports

This is a Babel plugin, so it's typically not imported directly in application code. Instead, it's configured in Babel configuration files:

{
  "plugins": ["@babel/plugin-transform-classes"]
}

For programmatic use with Babel's transform API:

import transformClasses from "@babel/plugin-transform-classes";
import { transform } from "@babel/core";

CommonJS:

const transformClasses = require("@babel/plugin-transform-classes");
const { transform } = require("@babel/core");

Basic Usage

Babel Configuration

.babelrc.json:

{
  "plugins": [
    ["@babel/plugin-transform-classes", { "loose": false }]
  ]
}

babel.config.js:

module.exports = {
  plugins: [
    ["@babel/plugin-transform-classes", { loose: true }]
  ]
};

Programmatic Usage

import { transform } from "@babel/core";
import transformClasses from "@babel/plugin-transform-classes";

const code = `
class MyClass extends BaseClass {
  constructor(name) {
    super();
    this.name = name;
  }
  
  greet() {
    return "Hello, " + this.name;
  }
  
  static create(name) {
    return new MyClass(name);
  }
}
`;

const result = transform(code, {
  plugins: [[transformClasses, { loose: false }]]
});

console.log(result.code);

Architecture

The plugin operates through Babel's visitor pattern and relies heavily on Babel's runtime helper system:

  • Plugin Factory: Uses Babel's declare() helper to create plugin configuration, integrating with Babel's assumption system
  • AST Visitors: Processes ClassDeclaration, ClassExpression, and ExportDefaultDeclaration nodes during compilation
  • Transform Engine: Core logic in transformClass.ts converts class structures to function-based equivalents using IIFEs
  • Helper Integration: Depends on Babel runtime helpers (createClass, inherits, callSuper, classCallCheck, etc.)
  • Assumption System: Integrates with Babel's assumptions (setClassMethods, constantSuper, etc.) for optimized output

Capabilities

Plugin Configuration

The main plugin export that integrates with Babel's transform pipeline using the declare helper.

/**
 * Main plugin factory function created using Babel's declare helper
 * @param api - Babel API object providing utilities, version checking, and assumptions
 * @param options - Plugin configuration options
 * @returns Babel plugin configuration object
 */
declare function default(api: BabelAPI, options: Options): BabelPlugin;

interface Options {
  /** Enable loose mode for simpler, faster output with fewer spec compliance checks */
  loose?: boolean;
}

interface BabelAPI {
  /** Assert minimum Babel version requirement */
  assertVersion(version: number): void;
  /** Get current compilation targets */
  targets(): any;
  /** Get assumption value with optional fallback */
  assumption(name: string): boolean | undefined;
}

interface BabelPlugin {
  /** Plugin identifier */
  name: "transform-classes";
  /** AST visitor configuration */
  visitor: {
    ExportDefaultDeclaration(path: NodePath<t.ExportDefaultDeclaration>): void;
    ClassDeclaration(path: NodePath<t.ClassDeclaration>): void;
    ClassExpression(path: NodePath<t.ClassExpression>, state: PluginState): void;
  };
}

interface PluginState {
  file: File;
  opts: Options;
}

Configuration Examples:

// Strict mode (default) - full ES6 spec compliance
module.exports = {
  plugins: ["@babel/plugin-transform-classes"]
};

// Loose mode - simpler output, better performance
module.exports = {
  plugins: [
    ["@babel/plugin-transform-classes", { loose: true }]
  ]
};

Class Declaration Transformation

Transforms ES6 class declarations into ES5 variable declarations with function constructors.

Input:

class MyClass {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    return "Hello, " + this.name;
  }
}

Output (loose: false):

var MyClass = /*#__PURE__*/function () {
  "use strict";

  function MyClass(name) {
    babelHelpers.classCallCheck(this, MyClass);
    this.name = name;
  }
  var _proto = MyClass.prototype;
  _proto.greet = function greet() {
    return "Hello, " + this.name;
  };
  return babelHelpers.createClass(MyClass);
}();

Class Expression Transformation

Transforms ES6 class expressions into immediately invoked function expressions (IIFEs).

Input:

const MyClass = class {
  constructor(value) {
    this.value = value;
  }
};

Output:

var MyClass = /*#__PURE__*/function () {
  "use strict";

  function _class(value) {
    babelHelpers.classCallCheck(this, _class);
    this.value = value;
  }
  return babelHelpers.createClass(_class);
}();

Inheritance Support

Handles class inheritance with extends keyword and super() calls.

Input:

class Child extends Parent {
  constructor(name, age) {
    super(name);
    this.age = age;
  }
  
  info() {
    return super.info() + ", age: " + this.age;
  }
}

Output:

var Child = /*#__PURE__*/function (_Parent) {
  "use strict";

  function Child(name, age) {
    var _this;
    _this = babelHelpers.callSuper(this, Child, [name]);
    _this.age = age;
    return babelHelpers.assertThisInitialized(_this);
  }
  babelHelpers.inherits(Child, _Parent);
  var _proto = Child.prototype;
  _proto.info = function info() {
    return babelHelpers.get(babelHelpers.getPrototypeOf(Child.prototype), "info", this).call(this) + ", age: " + this.age;
  };
  return babelHelpers.createClass(Child);
}(Parent);

Static Methods

Transforms static class methods into function properties.

Input:

class Utils {
  static format(text) {
    return text.toUpperCase();
  }
}

Output:

var Utils = /*#__PURE__*/function () {
  "use strict";

  function Utils() {
    babelHelpers.classCallCheck(this, Utils);
  }
  Utils.format = function format(text) {
    return text.toUpperCase();
  };
  return babelHelpers.createClass(Utils);
}();

Export Default Class

Handles exported class declarations by splitting the export and class definition.

Input:

export default class MyClass {
  constructor() {}
}

Output:

var MyClass = /*#__PURE__*/function () {
  "use strict";

  function MyClass() {
    babelHelpers.classCallCheck(this, MyClass);
  }
  return babelHelpers.createClass(MyClass);
}();

export { MyClass as default };

Types

interface Options {
  /** 
   * Enable loose mode for simpler output.
   * - loose: true - generates simpler, faster code with fewer spec compliance checks
   * - loose: false (default) - full ES6 spec compliance with runtime checks
   */
  loose?: boolean;
}

interface ClassAssumptions {
  /** Use simple assignments instead of Object.defineProperty for class methods */
  setClassMethods: boolean;
  /** Assume super class doesn't change during execution */
  constantSuper: boolean;
  /** Assume super constructors are callable (not just constructable) */
  superIsCallableConstructor: boolean;
  /** Don't add runtime checks for calling class as function */
  noClassCalls: boolean;
}

interface NodePath<T = t.Node> {
  /** AST node being processed */
  node: T;
  /** Replace current node with new node(s) */
  replaceWith(node: t.Node | t.Node[]): void;
  /** Split export declaration into separate export and declaration */
  splitExportDeclaration?(): void;
  /** Ensure function has a name */
  ensureFunctionName?(supportUnicodeId: boolean): NodePath | void;
  /** Check if node is of specific type */
  isClassDeclaration(): this is NodePath<t.ClassDeclaration>;
  isClassExpression(): this is NodePath<t.ClassExpression>;
  isCallExpression(): this is NodePath<t.CallExpression>;
  isArrowFunctionExpression(): this is NodePath<t.ArrowFunctionExpression>;
  /** Convert arrow function to regular function expression */
  arrowFunctionToExpression(): void;
  /** Access parent path */
  parentPath: NodePath;
  /** Access child paths */
  get(key: string): NodePath;
  /** Access scope information */
  scope: Scope;
}

interface Scope {
  /** Generate unique identifier */
  generateUidIdentifier(name?: string): t.Identifier;
}

interface File {
  /** File metadata and state */
  [key: string]: any;
}

/** Core Babel types namespace */
declare namespace t {
  interface Node {
    type: string;
  }
  
  interface ClassDeclaration extends Node {
    type: "ClassDeclaration";
    id: Identifier | null;
  }
  
  interface ClassExpression extends Node {
    type: "ClassExpression";
    id: Identifier | null;
  }
  
  interface ExportDefaultDeclaration extends Node {
    type: "ExportDefaultDeclaration";
    declaration: Node;
  }
  
  interface Identifier extends Node {
    type: "Identifier";
    name: string;
  }
  
  interface VariableDeclaration extends Node {
    type: "VariableDeclaration";
  }
  
  interface VariableDeclarator extends Node {
    type: "VariableDeclarator";
  }
  
  interface CallExpression extends Node {
    type: "CallExpression";
  }
  
  interface ArrowFunctionExpression extends Node {
    type: "ArrowFunctionExpression";
  }
  
  // Helper functions
  function cloneNode(node: Node): Node;
  function toExpression(node: Node): Node;
  function variableDeclaration(kind: "var" | "let" | "const", declarations: VariableDeclarator[]): VariableDeclaration;
  function variableDeclarator(id: Identifier, init: Node): VariableDeclarator;
  function inherits(child: Node, parent: Node): void;
}

Helper Dependencies

The plugin generates code that relies on Babel runtime helpers. These helpers must be available at runtime:

Required Helpers

/** Core helpers used by the plugin */
interface BabelHelpers {
  /** Creates the class constructor function with proper prototype chain */
  createClass(constructor: Function, protoMethods?: any[], staticMethods?: any[]): Function;
  /** Checks that class is not called as function */
  classCallCheck(instance: any, Constructor: Function): void;
  /** Sets up inheritance chain between child and parent */
  inherits(subClass: Function, superClass: Function): void;
  /** Calls super constructor with proper binding */
  callSuper(object: any, Constructor: Function, args?: any[]): any;
  /** Ensures 'this' is initialized after super call */
  assertThisInitialized(self: any): any;
  /** Gets property from prototype chain */
  get(object: any, property: string, receiver?: any): any;
  /** Gets prototype of object */
  getPrototypeOf(object: any): any;
}

Helper Configuration

To use these helpers, you need either:

  1. @babel/runtime (recommended):
{
  "plugins": [
    ["@babel/plugin-transform-runtime", {
      "helpers": true
    }],
    "@babel/plugin-transform-classes"
  ]
}
  1. Global helpers (older approach):
{
  "presets": [["@babel/preset-env", { "useBuiltIns": "usage" }]],
  "plugins": ["@babel/plugin-transform-classes"]
}

Babel Assumptions Integration

The plugin integrates with Babel's assumptions system for optimization:

// babel.config.js with assumptions
module.exports = {
  assumptions: {
    "setClassMethods": true,        // Use assignments for methods
    "constantSuper": true,          // Super doesn't change
    "superIsCallableConstructor": true,  // Super is callable
    "noClassCalls": true           // Classes won't be called as functions
  },
  plugins: ["@babel/plugin-transform-classes"]
};

These assumptions enable more optimized output when you can guarantee certain usage patterns in your code.