Now that TypeScript 2.2 supports Mixins through Class expressions we have a much better way to express Mixins on Components. Mind you that you can also use Component inheritance since angular 2.3 (discussion) or a custom decorator as discussed in other answers here. However, I think Mixins have some properties that make them preferable for reusing behavior across components:
I strongly suggest you read the TypeScript 2.2 announcement above to understand how Mixins work. The linked discussions in angular GitHub issues provide additional detail.
You'll need these types:
export type Constructor<T> = new (...args: any[]) => T;
export class MixinRoot {
}
And then you can declare a Mixin like this Destroyable
mixin that helps components keep track of subscriptions that need to be disposed in ngOnDestroy
:
export function Destroyable<T extends Constructor<{}>>(Base: T) {
return class Mixin extends Base implements OnDestroy {
private readonly subscriptions: Subscription[] = [];
protected registerSubscription(sub: Subscription) {
this.subscriptions.push(sub);
}
public ngOnDestroy() {
this.subscriptions.forEach(x => x.unsubscribe());
this.subscriptions.length = 0; // release memory
}
};
}
To mixin Destroyable
into a Component
, you declare your component like this:
export class DashboardComponent extends Destroyable(MixinRoot)
implements OnInit, OnDestroy { ... }
Note that MixinRoot
is only necessary when you want to extend
a Mixin composition. You can easily extend multiple mixins e.g. A extends B(C(D))
. This is the obvious linearization of mixins I was talking about above, e.g. you're effectively composing an inheritnace hierarchy A -> B -> C -> D
.
In other cases, e.g. when you want to compose Mixins on an existing class, you can apply the Mixin like so:
const MyClassWithMixin = MyMixin(MyClass);
However, I found the first way works best for Components
and Directives
, as these also need to be decorated with @Component
or @Directive
anyway.