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

Mixin Pattern

A mixin is a reusable object-oriented pattern that adds behavior from one class-like component to another class. In TypeScript, mixins are commonly implemented with functions that extend a base constructor.

What Is a Mixin?

A mixin adds reusable behavior to a class without requiring multiple inheritance — a mixin function takes a constructor as input and returns a new constructor that has all the original members plus the added ones.

Example: What Is a Mixin?

typescript
type Constructor<T = {}> = new (...args: any[]) => T;
function Timestamped<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    timestamp = Date.now();
  };
}
class Point {}
class TimestampedPoint extends Timestamped(Point) {}
console.log(typeof new TimestampedPoint().timestamp);

Mixin with Methods

A mixin can add one or more methods to whatever class it's applied to; the class returned from the mixin function carries both the original class's members and the new behavior the mixin contributed.

Example: Mixin with Methods

typescript
type Constructor<T = {}> = new (...args: any[]) => T;
function Serializable<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    serialize() { return JSON.stringify(this); }
  };
}
class Point { x = 1; y = 2; }
class SerializablePoint extends Serializable(Point) {}
console.log(new SerializablePoint().serialize());

Combining Mixins

Multiple mixins can be chained one after another, with each mixin function receiving the constructor that the previous mixin in the chain already returned, layering capabilities on top of each other.

Example: Combining Mixins

typescript
type Constructor<T = {}> = new (...args: any[]) => T;
function Named<TBase extends Constructor>(Base: TBase) {
  return class extends Base { name = "unnamed"; };
}
function Aged<TBase extends Constructor>(Base: TBase) {
  return class extends Base { age = 0; };
}
class Base {}
class Person extends Aged(Named(Base)) {}
const p = new Person();
console.log(p.name, p.age);

Mixin State

Mixins can add instance fields as well as methods — those fields belong to each individual instance created from the returned class, so every instance gets its own independent copy of that state.

Example: Mixin State

typescript
type Constructor<T = {}> = new (...args: any[]) => T;
function Counter<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    count = 0;
    increment() { this.count++; }
  };
}
class Base {}
class Widget extends Counter(Base) {}
const w1 = new Widget();
const w2 = new Widget();
w1.increment();
console.log(w1.count, w2.count);

Mixin Benefits

Mixins pay off when several otherwise-unrelated classes need the exact same behavior, encouraging small, composable capabilities instead of forcing everything into one deep, rigid inheritance hierarchy.

Example: Mixin Benefits

typescript
type Constructor<T = {}> = new (...args: any[]) => T;
function Loggable<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    log(msg: string) { console.log(`[LOG] ${msg}`); }
  };
}
class Service {}
class ApiService extends Loggable(Service) {}
new ApiService().log("Request received");
🔒

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.