普通视图

发现新文章,点击刷新页面。
昨天以前首页

神奇魔法类:使用 createMagicClass 增强你的 JavaScript/Typescript 类

2025年8月17日 11:40

什么是神奇魔法类?

神奇魔法类(Magic Class)是一种特殊的类包装器,它通过createMagicClass函数创建,能够赋予普通 JavaScript/TypeScript 类超能力。这个工具让你的类既可以作为构造函数使用,又可以作为函数调用来配置选项,大大增强了类的灵活性和可用性。

神奇特性

1. 双重身份

魔法类具有双重身份,可以:

  • 作为普通类使用用于继承:class MyClass extends MagicClass
  • 作为函数调用来传入选项用于构建类:class MyClass extends MagicClass({<options>})

2. 生命周期钩子

提供完整的生命周期钩子,让你能够精确控制实例的创建过程:

  • onBeforeInstance: 实例创建前触发,可以阻止实例创建或修改类
  • onAfterInstance: 实例创建后触发,可以对实例进行后处理
  • onErrorInstance: 实例创建出错时触发,可以进行错误处理

使用示例

基本用法

import { createMagicClass } from "flex-tools/classs";
type UserCreateOptions = {
  prefix?: string;
  x?: number;
};
// 定义一个普通类
class User {
  name: string;
  prefix: string = "";
  constructor(name: string) {
    this.name = name;
    this.prefix = getMagicClassOptions<UserCreateOptions>(this)?.prefix!;
  }
  get title() {
    return `${this.prefix}${this.name}`;
  }
  toString() {
    return `${this.constructor.name}<${this.name}>`;
  }
}

// 创建魔术类
const MagicUser = createMagicClass<typeof User, UserCreateOptions>(User, {
  prefix: "Hi,", // 默认配置
  x: 1,
  onBeforeInstance: (cls, args, _options) => {},
  onAfterInstance: (inst, _options) => {},
});
//  直接作为类使用
class Admin extends MagicUser {}
class Guest extends MagicUser({ x: 2, prefix: "欢迎," }) {}
class Customer extends MagicUser({ prefix: "尊贵的" }) {}

const user = new User("用户");
const admin = new Admin("管理员");
const guest = new Guest("访客");
const customer = new Customer("客户");

高级用法:拦截实例创建

const ValidatedPerson = createMagicClass(Person, {
  onBeforeInstance: (cls, args, options) => {
    const name = args[0];

    // 验证名称
    if (!name || name.length < 2) {
      throw new Error("Name must be at least 2 characters long");
    }

    // 可以修改参数
    args[0] = name.charAt(0).toUpperCase() + name.slice(1);

    // 返回false会阻止实例创建
    // 返回一个对象会使用该对象作为实例
    // 返回一个类会使用该类创建实例
  },
  onErrorInstance: (error, cls, options) => {
    console.error("Failed to create person:", error.message);
  },
});

class SitePerson extends ValidatedPerson {}

// 这将抛出错误,因为名称太短
try {
  const invalid = new SitePerson("A");
} catch (e) {
  console.log(e.message); // "Name must be at least 2 characters long"
}

// 这将成功,并且名称首字母会被自动大写
const valid = new SitePerson("bob"); // 实际名称将是 "Bob"

获取实例配置

你可以使用getMagicClassOptions函数获取实例的配置选项:

import { createMagicClass, getMagicClassOptions } from "flex-tools/classs";

const MagicPerson = createMagicClass(Person, { version: "1.0" });
const ConfiguredPerson = MagicPerson({ theme: "dark" });
const person = new ConfiguredPerson("Alice");

const options = getMagicClassOptions(person);
console.log(options); // { version: '1.0', theme: 'dark' }

总结

神奇魔法类通过createMagicClass函数提供了一种优雅而强大的方式来增强 JavaScript/TypeScript 类的能力。它不仅保留了原始类的所有功能,还添加了配置选项、生命周期钩子和灵活的实例化方式,使你的代码更加灵活、可配置且易于维护。

无论你是构建复杂的 UI 组件、可配置的工具类,还是需要精细控制实例创建过程的系统,神奇魔法类都能为你提供强大而灵活的解决方案。

详见flex-tools

❌
❌