Dynamic mixins and feature inheritance

This is an interesting bit of code I was playing with to dynamically inherit from multiple classes. Note that this isn’t something I’d recommend using - it’s somewhat hard to read and reason about, and I have no idea of the performance impact.

Version 1

// Library function which is used as the "extends" call.
const mix = (...mixins) =>
	mixins.reduce(
		(combinedClass, mixinApplier) => mixinApplier(combinedClass),
		class {}
	);

// These features can be shared across many classes.
const FooFeature = superclass =>
	class extends superclass {
		foo() {
			console.log("foo");
		}
	};
const BarFeature = superclass =>
	class extends superclass {
		bar() {
			console.log("bar");
		}
	};

// Our final class inherits from all the declared features.
class MyThing extends mix(FooFeature, BarFeature) {
	constructor(...args) {
		super(...args);
		console.log("I'm a proper instance");
	}
}

const instance = new MyThing(); // => I'm a proper instance
instance.foo() // => foo
instance.bar() // => bar

I didn’t particularly like the mix syntax, and it didn’t strike me as very declarative in the style of the React code I’d been writing. I rewrote it so that the parent classes can be defined within the child class.

Version 2

class Mixable {
	constructor() {
		this.constructor[Mixable.extends].forEach(mixin =>
			Object.assign(this, mixin)
		);
	}
}

const FooFeature = {
	foo() {
		console.log("foo");
	}
};

const BarFeature = {
	bar() {
		console.log("bar");
	}
};

class MyThing extends Mixable {
	static get [Mixable.extends]() {
		return [FooFeature, BarFeature];
	}

	constructor(...args) {
		super(...args);
		console.log("I'm a proper instance");
	}
}

const instance = new MyThing(); // => I'm a proper instance
instance.foo(); // => foo
instance.bar(); // => bar

I prefer this, but the static get [Mixable.extends]() syntax is a bit much. I did it like this so that there’s no chance the extension declaration can clash with a method name, but it’s hard to read.

Again, this isn’t something I recommend doing - I just thought it was interesting.

Back to notes