Reuse functionality across classes without complex inheritance. Just Works™ with TypeScript.
const IdentifiableItem = mixin(StoreItem, [Identifiable])
// item is StoreItem & Identifiable
const item = new IdentifiableItem()
// reuse functionality across classes
const User = mixin(Person, [Identifiable])
No casting objects as an interface, no any
. typed-mixins
work perfectly out of the box with TypeScript.
npm install typed-mixins
Or
yarn add typed-mixins
From Stack Overflow:
A mixin is a special kind of multiple inheritance. There are two main situations where mixins are used:
- You want to provide a lot of optional features for a class.
- You want to use one particular feature in a lot of different classes.
Think of mixins as an interface
with an implementation attached.
Mixins shouldn't be overused, but they are a useful way to get around complex inheritance trees.
import { mixin } from 'typed-mixins'
import { v4 as uuidv4 } from 'uuid';
class StoreItem {
name: string;
price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
}
class Person {
email: string;
}
class Identifiable {
static getRandomId(): string {
return uuidv4();
}
private _id = uuidv4()
get id(): string {
return _id;
}
matches(otherItem: Identifiable): boolean {
return otherItem.id === this.id;
}
}
const IdentifiableItem = mixin(StoreItem, [Identifiable])
// item is StoreItem & Identifiable
const item = new IdentifiableItem('mug', 10)
// shorthand for mixed class
let nextItem: typeof IdentifiableItem.Instance
// use instance properties
console.log(item.name) // 'mug'
console.log(item.id) // some UUID
console.log(item.matches(item)) // true
const User = mixin(Person, [Identifiable])
console.log(person.id) // another UUID
// use static properties
console.log(User.getRandomId()) // random UUID
You can further customize mixed classes:
const IdentifiableItem = mixin(StoreItem, [Identifiable])
class Audiobook extends IdentifiableItem {
length: number;
author: string;
}
- The base class and all mixins must be classes. No plain-old JavaScript objects.
- Mixin classes cannot use constructor arguments (prevents really tortured syntax in the returned constructor)
- This package ships as ES6 because transpiled ES5 classes cannot extend native classes