Hegel: support for class-factory mixins

Created on 20 May 2020  路  5Comments  路  Source: JSMonk/hegel

The following plain JS doesn't work:

function Foo(Base) {
  return class Foo extends Base {
    foo() { console.log('foo') }
  }
}

class Bar {
  bar() { console.log('bar') }
}

class Baz extends Foo(Bar) {
  baz() { console.log('baz') }
}

const b = new Baz
b.foo()
b.bar()
b.baz()

try link

enhancement

Most helpful comment

As another example of the current complexity, here's my Mixin implementation (which itself isn't that long) and the unit tests (but the README has better more practical examples). But it gets complicated at the usage sites, for example.

It is riddled with issues. For example, in that last example, if I change the lines

const _Base = Constructor(Base)
const Parent = Observable.mixin(TreeNode.mixin(_Base))

to

const Parent = Observable.mixin(TreeNode.mixin(Constructor(Base)))

it completely breaks (for no intuitive reason). The Constructor(Base) constructor expression must be assigned to a new variable first, for it to work.

It's little things like that, plus all the other issues like having to follow the patterns with the mapped typed that you see in that example, that make it all too complicated compared to plain JS.

All 5 comments

Thank you a lot ^_^.
We will add it soon.

I'm curious if it can be better than TS's. There are several problems with mixins in TypeScript:

Another example

The following is amazing, yet horrific: https://www.bryntum.com/blog/the-mixin-pattern-in-typescript-all-you-need-to-know-part-2/

It is amazing that that technique for making class-factory mixins in TypeScript can make them more class-like, but the syntax, non-DRY-ness (or WET-ness as in Write Everything Twice), and complicated mapped types are the horrific part.

If Hegel could achieve mixins but without all that complexity, and with support for declaration emit (or in other words full support for mixins as library exports, unlike in TypeScript), I would seriously consider dropping TypeScript for Hegel. Is it possible, without mapped types? I suppose it would be like hidden mapped types within the Hegel implementation, without mapped types required by the user?

As another example of the current complexity, here's my Mixin implementation (which itself isn't that long) and the unit tests (but the README has better more practical examples). But it gets complicated at the usage sites, for example.

It is riddled with issues. For example, in that last example, if I change the lines

const _Base = Constructor(Base)
const Parent = Observable.mixin(TreeNode.mixin(_Base))

to

const Parent = Observable.mixin(TreeNode.mixin(Constructor(Base)))

it completely breaks (for no intuitive reason). The Constructor(Base) constructor expression must be assigned to a new variable first, for it to work.

It's little things like that, plus all the other issues like having to follow the patterns with the mapped typed that you see in that example, that make it all too complicated compared to plain JS.

I'm also interested in class mixins, and the developer experience with TypeScript has been quite painful in this regard.

Here is one more issue which wasn't mentioned above: microsoft/TypeScript#17744. See my comment there for an overview of techniques that I tried, including the workaround for using protected methods.

Generally, this might be beneficial for web components libraries, such as Lion, Vaadin, Spectrum and others.
We have to use class mixins when creating custom elements classes that extend HTMLElement.

Was this page helpful?
0 / 5 - 0 ratings