Skip to content

hasnainroopawalla/power-mixin

Repository files navigation

power-mixin

Minified Size

Overview

power-mixin is a lightweight TypeScript Mixin framework. The Mixin pattern is meant to add reusable functionality to objects without any class inheritance.

Features

  • Intuitive way to create Mixins for easy integration into existing systems.
  • Strong type-safety during compilation, along with runtime safety while creating and initializing the Mixins.
  • Provides inter-class reusability of attributes (props/methods) by passing the mixed object to the initializer (constructor).

🏁 Getting started

$ npm install power-mixin
// OR
$ yarn add power-mixin

💡 Quick start

A Bank system where the core functionality is mixed in from various existing classes like Amount and Deposit:

import { BaseMixin } from "power-mixin";

type IAmount = {
  amount: number;
  setAmount: (newAmount: number) => void;
};

// Basic class to manage the amount
class Amount implements IAmount {
  public amount: number = 1000;

  constructor(private readonly bank: IBank) {}

  public setAmount(newAmount: number): void {
    this.amount = newAmount;
  }
}

// Define the Amount Mixin
class AmountMixin extends BaseMixin<IBank, IAmount> {
  constructor() {
    super({
      // Specify the methods and props to be be mixed
      methods: ["setAmount"],
      props: ["amount"],
      initMixin: bank => new Amount(bank),
    });
  }
}
import { BaseMixin } from "power-mixin";

type IDeposit = {
  deposit: (amount: number) => void;
};

// Basic class to deposit money into the account
class Deposit implements IDeposit {
  constructor(private readonly bank: IBank) {}

  public deposit(depositAmount: number): void {
    this.bank.setAmount(this.bank.amount + depositAmount);
  }
}

// Define the Deposit Mixin
class DepositMixin extends BaseMixin<IBank, IDeposit> {
  constructor() {
    super({
      // Specify the methods and props to be be mixed
      methods: ["deposit"],
      props: [],
      initMixin: bank => new Deposit(bank),
    });
  }
}

Define the IBank interface to represent the Mixed object based on the above Mixins:

type IBank = IAmount & IDeposit;

Create the mixed bank object using an input list of Mixin implementations:

import { mix } from "power-mixin";

const bank = mix<IBank>({
  mixins: [new AmountMixin(), new DepositMixin()],
});

// Complete type-safety for the mixed object
console.log(bank.amount); // 1000
bank.deposit(500);
console.log(bank.amount); // 500
bank.setAmount(2000);
console.log(bank.amount); // 2000

Runtime safety is guaranteed in the following scenarios:

  • Attempting to bind a method as a prop and vice versa.
  • Attempting to bind a prop/method that already exists on the object.

✏️ Contributing

  • Post any issues and suggestions on the GitHub issues page.
  • To contribute, fork the project and then create a pull request back to main.