Mixins

A big flaw of inheritance in the world of OOP is that it is limited to one level. This means you cannot extend more than a single class which can get messy quickly as you end up with large classes that have multiple responsibilities.

TypeScript has something called mixins. They act somewhat like traits in PHP, with the major difference being that under the hood they extend an object and return that. The result of that is rather than simply adding some methods, a completely new object is created that contains the old and new methods.

Mixins are a powerful tool to make use of composition over inheritance but they should be used with caution, as with everything, or you’ll end up with the same issues that come with the excessive use of inheritance.

Mixins Usage

1// Class we will extend through a mixin
2class Block {}
3 
4// Function that serves as mixin
5function Timestamped<TBase extends Constructor>(Base: TBase) {
6 return class extends Base {
7 timestamp = new Date("2019-09-01");
8 };
9}
10 
11// Types
12type AnyFunction<T = any> = (...input: any[]) => T;
13type Mixin<T extends AnyFunction> = InstanceType<ReturnType<T>>;
14type TTimestamped = Mixin<typeof Timestamped>;
15type MixinBlock = TTimestamped & Block;
16 
17// Register the Mixin
18app
19 .get<Services.Mixin.MixinService>(Container.Identifiers.MixinService)
20 .set("timestamped", Timestamped);
21 
22// Apply the mixin
23const block: MixinBlock = new (
24 app
25 .get<Services.Mixin.MixinService>(Container.Identifiers.MixinService)
26 .apply<MixinBlock>("timestamped", Block)
27)();
28 
29// Ensure the mixin did its job
30console.log(block.timestamp === new Date("2019-09-01"));
Last updated 9 months ago
Edit Page
Share: