This popped into my news feed a couple days ago and it seemed like a really neat feature that’s been added into version 2.2. of TypeScript – the concept of mixins.
This terminology (mixin) has been available in SASS for quite a while and provides the ability to extend functionality by composing functionality from various sources. This same concept holds true in TypeScript.
A few examples based off a User class:
1 2 3 4 5 6 7 |
class User { name: string; constructor(name: string) { this.name = name; } } |
Now a couple mixins:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
type Constructor<T> = new (...args: any[]) => T; type Constructable = Constructor<{}>; function Tagged<TBase extends Constructable>(Base: TBase) { return class extends Base { tag: string | null; }; } function Activatable<TBase extends Constructable>(Base: TBase) { return class extends Base { private _isActivated = false; get isActivated(): boolean { return this._isActivated; } activate() { this._isActivated = true; } deactivate() { this._isActivated = false; } }; } |
The first adds the ability to ‘tag’ the base class, the second exposes a couple methods to activate/deactivate the class.
Pulling this together you can then create basic TaggableUser:
1 2 3 4 5 6 |
const TaggableUser = Tagged(User); const user = new TaggableUser("Tagged User"); console.log(user.name); user.tag = "Tagged User tag"; console.log(user.tag); |
Or an ActivatableUser:
1 2 3 4 5 6 7 |
const ActivatableUser = Activatable(User); const activatableUser = new ActivatableUser("Activatable User"); console.log(activatableUser.name); console.log(activatableUser.isActivated); activatableUser.activate(); console.log(activatableUser.isActivated); |
Or even better, a combination of both:
1 2 3 4 5 6 7 |
const ActivatableAndTaggedUser = Activatable(Tagged(User)); const activatableAndTaggedUser = new ActivatableAndTaggedUser("Activatable and Tagged User"); console.log(activatableAndTaggedUser.name); console.log(activatableAndTaggedUser.isActivated); activatableAndTaggedUser.activate(); console.log(activatableAndTaggedUser.isActivated); |
Pretty neat huh?
The inspiration for this came from https://blog.mariusschulz.com/2017/05/26/typescript-2-2-mixin-classes