← Back to TypeScript Course | Chapter 22: Mixins | Lesson 2 of 4

Applying Mixins

Applying a mixin means passing a base class through a mixin function and using the returned class. Multiple mixins can be chained to build a class with several capabilities.

Applying One Mixin

Start with a plain base class and pass its constructor into a mixin function — the constructor that comes back out represents the enhanced class with the mixin's behavior added on top.

Example: Applying One Mixin

typescript
type Constructor<T = {}> = new (...args: any[]) => T;
function Flyable<TBase extends Constructor>(Base: TBase) {
  return class extends Base { fly() { return "Flying"; } };
}
class Bird {}
class FlyingBird extends Flyable(Bird) {}
console.log(new FlyingBird().fly());

Applying Multiple Mixins

Nesting mixin calls creates a class carrying every capability supplied by each mixin in the chain; the order can matter whenever a later mixin depends on members a mixin earlier in the chain already added.

Example: Applying Multiple Mixins

typescript
type Constructor<T = {}> = new (...args: any[]) => T;
function Swimmable<TBase extends Constructor>(Base: TBase) {
  return class extends Base { swim() { return "Swimming"; } };
}
function Flyable<TBase extends Constructor>(Base: TBase) {
  return class extends Base { fly() { return "Flying"; } };
}
class Duck {}
class SuperDuck extends Swimmable(Flyable(Duck)) {}
const duck = new SuperDuck();
console.log(duck.fly(), duck.swim());

Mixin Composition Function

A small helper function can centralize the application of several mixins at once, turning a chain of nested function calls into one readable, reusable composition step.

Example: Mixin Composition Function

typescript
type Constructor<T = {}> = new (...args: any[]) => T;
function Flyable<TBase extends Constructor>(Base: TBase) {
  return class extends Base { fly() { return "flying"; } };
}
function Swimmable<TBase extends Constructor>(Base: TBase) {
  return class extends Base { swim() { return "swimming"; } };
}
function compose<TBase extends Constructor>(Base: TBase) {
  return Swimmable(Flyable(Base));
}
class Animal {}
const Duck = compose(Animal);
console.log(new Duck().fly(), new Duck().swim());

Mixins with Constructors

A mixin can preserve whatever constructor arguments the base class expects by extending that base class directly — the mixin itself should avoid assuming a fixed constructor signature unless it explicitly constrains one.

Example: Mixins with Constructors

typescript
type Constructor<T = {}> = new (...args: any[]) => T;
function Named<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    constructor(...args: any[]) {
      super(...args);
    }
  };
}
class Person {
  constructor(public name: string) {}
}
class NamedPerson extends Named(Person) {}
console.log(new NamedPerson("Ravi").name);

Mixin Usage Patterns

Keep individual mixin functions small and focused on one capability. Create a named, reusable enhanced constructor when a particular combination gets applied repeatedly, or just apply mixins inline for a one-off class.

Example: Mixin Usage Patterns

typescript
type Constructor<T = {}> = new (...args: any[]) => T;
function Loggable<TBase extends Constructor>(Base: TBase) {
  return class extends Base { log() { console.log("logging"); } };
}
class Service {}
// Applied inline for a one-off class:
class OneOffService extends Loggable(Service) {}
new OneOffService().log();
🔒

Chapter Quiz — Complete all 4 topics to unlock

0/4 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.