Skip to content

Instantly share code, notes, and snippets.

@koshuang
Last active August 23, 2017 20:54
Show Gist options
  • Select an option

  • Save koshuang/f11f1fbfb2d1bcb0c72dd2f9e7f5a5fe to your computer and use it in GitHub Desktop.

Select an option

Save koshuang/f11f1fbfb2d1bcb0c72dd2f9e7f5a5fe to your computer and use it in GitHub Desktop.
const composeMixins = (...fns) => (
obj = {},
piped = x => fns.reduce((o, fn) => fn(o), x)
) => piped(obj);
const user = {
name: 'kos',
email: 'test@test.com',
};
const nameTrait = obj => ({ ...obj, getName: () => obj.name });
const emailTrait = obj => ({ ...obj, getEmail: () => obj.email });
const mixins = composeMixins(nameTrait, emailTrait);
const newUser = mixins(user);
console.log(newUser.getName()); // kos
console.log(newUser.getEmail()); // test@test.com
@ericelliott

ericelliott commented Apr 19, 2017

Copy link
Copy Markdown

Here's a slightly better version:

const composeMixins = (...mixins) => (
  instance = {},
  mix = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x)
) => mix(...mixins)(instance);

Note that you can customize the mixing behavior. For example, if you want to compose with first-in precedence instead of last-in:

const a = (instance) => Object.assign(instance, {
  foo: 1
});

const b = (instance) => Object.assign(instance, {
  foo: 2
});

const c1 = composeMixins(a, b);
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);

const r1 = c1({}); // {foo: 2}
const r2 = c1({}, compose); // {foo: 1}

@koshuang

Copy link
Copy Markdown
Author

@ericelliott that's helpful, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment