TypeScript (and JavaScript) classes support strict single inheritance. So you cannot do:
classUserextendsTagged,Timestamped { // ERROR : no multiple inheritance}
Another way of building up classes from reusable components is to build them by combining simpler partial classes called mixins.
The idea is simple, instead of a class A extending class B to get its functionality, function B takes class A and returns a new class with this added functionality. Function B is a mixin.
[A mixin is] a function that 1. takes a constructor, 1. creates a class that extends that constructor with new functionality 1. returns the new class
A complete example
// Needed for all mixinstypeConstructor<T= {}> =new (...args:any[]) =>T;////////////////////// Example mixins////////////////////// A mixin that adds a propertyfunctionTimestamped<TBaseextendsConstructor>(Base:TBase) {returnclassextendsBase { timestamp =Date.now(); };}// a mixin that adds a property and methodsfunctionActivatable<TBaseextendsConstructor>(Base:TBase) {returnclassextendsBase { isActivated =false;activate() {this.isActivated =true; }deactivate() {this.isActivated =false; } };}////////////////////// Usage to compose classes////////////////////// Simple classclassUser { name ='';}// User that is TimestampedconstTimestampedUser=Timestamped(User);// User that is Timestamped and ActivatableconstTimestampedActivatableUser=Timestamped(Activatable(User));////////////////////// Using the composed classes////////////////////consttimestampedUserExample=newTimestampedUser();console.log(timestampedUserExample.timestamp);consttimestampedActivatableUserExample=newTimestampedActivatableUser();console.log(timestampedActivatableUserExample.timestamp);console.log(timestampedActivatableUserExample.isActivated);
Let's decompose this example.
Take a constructor
Mixins take a class and extend it with new functionality. So we need to define what is a constructor. Easy as:
// Needed for all mixinstypeConstructor<T= {}> =new (...args:any[]) =>T;
Extend the class and return it
Pretty easy:
// A mixin that adds a propertyfunctionTimestamped<TBaseextendsConstructor>(Base:TBase) {returnclassextendsBase { timestamp =Date.now(); };}