”;
TypeScript is an Object-oriented programming language and contains the classes, which is a blueprint for the object. The class can be defined as shown below in TypeScript.
class MathOps { // defining a method add(a: number, b: number): void { console.log(''sum is: '', a + b); } }
Now, suppose we have multiple classes like the above which contain different operations.
What if you want to reuse both classes and want to create a third class by extending both classes? For example, if you try to extend the ”allOps” class with ”MathOps1”, and ”BitwiseOps” classes, TypeScript will give you an error as multiple inheritance is not allowed in TypeScript.
class allOps extends MathOps, BitwiseOps { // Executable code }
To solve the above problem, developers can use the mixins in TypeScript.
Introduction to Mixins
In TypeScript, mixins is a concept that allows us to extend a single class via multiple classes. This way, we can reuse the class components and combine their methods and properties in a single class.
We can use the declaration merging technique to extend the single class via multiple classes.
Declaration Merging
When you have two declarations of the same name, it will be merged without throwing any error.
For example, in the below code, we have defined the interface ”A” twice containing different properties. After that, we have created the ”obj” object of type ”A”, which contains the properties ”a” and ”b” as both interfaces ”A” are merged.
// Definition of an interface with the same name twice interface A { a: string; } interface A { b: string; } // Object that implements the interface let obj: A = { a: ''a'', b: ''b'' }; console.log(obj.a); // a console.log(obj.b); // b
On compiling, it will generate the following TypeScript code.
// Object that implements the interface let obj = { a: ''a'', b: ''b'' }; console.log(obj.a); // a console.log(obj.b); // b
Output
The output of the above example is as follows –
a b
Now, let”s understand how we can use the declaration merging technique to extend multiple classes with a single class.
Implementing Our Mixin Helper Function
Let”s understand the below example code line-by-line.
-
We have defined the ”swimmer” class, which contains the StartSwim() and EndSwim() methods.
-
Next, we have defined the Cyclist class, which contains startCycle() and endCycle() methods.
-
Next, the ”combineMixins()” function is a helper function that allows us to mix the properties and methods of two or more classes in one class. That”s why it is called mixin function.
-
The function takes the derived or parent class as a first parameter, and the array of base or child classes as a second parameter.
-
It iterates through the array of base classes using the forEach() method.
-
In the forEach() method callback, it iterates through each property of the single base class and adds in the prototype of the derived class using the defineProperty() method.
-
-
After that, we have defined the ”Biathlete” class.
-
The interface ”Biathlete” extends the ”Swimmer” and ”Cyclist” classes to merge all property and method declarations of both classes into the ”Biathlete” class. However, it won”t combine the implementation of methods.
-
Next, we call the ”combineMixins()” function which merges the implementations of methods of the classes in other classes.
-
Next, we created the instance of the ”Biathlete” class and used it to call the methods of the ”Swimmer” and ”Cyclist” classes.
// Swimmer class definition class Swimmer { // Methods StartSwim() { console.log(''Starting the swimming session...''); } EndSwim() { console.log(''Completed the swimming session.''); } } // Cyclist class definition class Cyclist { // Methods StartCycle() { console.log(''Starting the cycling session...''); } EndCycle() { console.log(''Completed the cycling session.''); } } // export class Biathlete extends Swimmer, Cyclist{} function combineMixins(derived: any, bases: any[]) { // Iterate over the base classes bases.forEach(base => { // Iterate over the properties of the base class Object.getOwnPropertyNames(base.prototype).forEach(name => { // Copy the properties of the base class to the derived class Object.defineProperty(derived.prototype, name, Object.getOwnPropertyDescriptor(base.prototype, name)); }); }); } // Export Biathlete class export class Biathlete { } // Use interface to combine mixins export interface Biathlete extends Swimmer, Cyclist { } // Combine mixins combineMixins(Biathlete, [Swimmer, Cyclist]); // Create an instance of Biathlete class const athlete = new Biathlete(); // Call the methods athlete.StartSwim(); athlete.EndSwim(); athlete.StartCycle(); athlete.EndCycle();
Output
Starting the swimming session... Completed the swimming session. Starting the cycling session... Completed the cycling session.
This way, we can merge the structure of two components using the interface. After that, we can use the mixins function to combine the implementations of two components into the third one and reuse them.
”;