CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-babel--plugin-transform-classes

Babel plugin that compiles ES2015 classes to ES5-compatible JavaScript code

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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.

docs

index.md

tile.json