Mixins with type checking in Typescript
If you want to use Typescript because you think that type checking is a good thing, and that your IDE is much more clever with Typescript, you’ll soon discover that one of best feature of JavaScript is missing in Typescript : the mixins. It is a very important design patern to reduce code repetition by composing objects using reusable pieces of code.
The only available solution, until now, was to duplicate class properties and method, in order to make the compiler happy then use a function to copy properties properties from mixin to the composed object. See official documentation on the subject.
Here I propose a way to compose objects using regular classes with no code duplication, no performance overhead, and with type checking.
Create the mixins with concrete classes
Let’s imagine we have 3 capabilities (our mixins) implemented as classes. To make it more fun, each of them initialize its data differently.
and we want some animals to have these capabilities
- the Duck is a Swimmer, a Walker, and a Talker (saying coin)
- the Fish is a Swimmer and a Talker (saying bloup)
Create an interface that extends the classes
It’s not possible in Typescript to create a class that extends those three classes. But what we can do is to create an interface that extends those classes. We can even define what signature the constructore should be.
In the same file we will create a variable with same name as the interface to store a constructor for this interface. Yes it’s valid Typescript. For now let’s imagine we have a compose
function that will create this constructor function.
All we have to do now, is to find a way to create concrete classes that implements theses interfaces.
Create a constructor function implementing the capabilities
The idea is to create a constructor function, whose prototype will receive the properties of our mixins. So here is the compose functon
Use new operator or a factory to create the objects
You can then use you Duck interface like in this sample.
A note on mixin initialization
What is really cool with this solution, is that mixins work as expected when reading the code:
- the properties are initialized
- the constructor is called
This is because Typescript aggregate all the initialization in the constructor function of the mixin, that we call when instantiating our composed object.
Full code
A working sample is available here: https://github.com/nch3v/typescript-mixins