Skip to content
tezvyn:
Menu

TypeScript Mixins: Building Classes from Reusable Parts

Source: typescriptlang.orgHardHow cards are made

A mixin is a function that takes a class and returns a new one with added features, like bolting on a turbocharger. Use it to share behavior (e.g., logging) across unrelated classes.

Why it exists

Traditional single inheritance can be too restrictive. You might want to add logging capabilities to both a User class and a DatabaseRequest class, but they don't share a common ancestor. Mixins provide a way to share behavior between classes without forcing them into the same inheritance chain.

The mental model

A mixin is a function that takes a class as input and returns a new, enhanced class as output. It's not inheritance; it's composition at the class level. Instead of a class being a certain type, you apply the behavior of that type to the class dynamically.

How it works

The pattern uses a function that accepts a generic constructor type. Inside this function, you define a class expression that extends the base class passed in. This new inner class contains the mixin's properties and methods. The function then returns this newly composed class. To apply the mixin, you simply call the function with your base class as the argument, which yields a new class definition that combines both.

When to use it

Use mixins to share functionality across different class hierarchies. This is perfect for cross-cutting concerns like serialization, event handling, or timestamping. For example, you can create a Timestampable mixin and apply it to Post, Comment, and User classes to add createdAt and updatedAt fields to all of them without a shared base class.

When not to use it

Avoid mixins for defining the core identity of a class. If a Dog's essential nature is that it's an Animal, use inheritance. Mixins are for supplemental, non-essential behaviors. Overusing them can create complex, hard-to-debug classes where it's unclear where any given method or property originates.

One canonical example

Imagine a Sprite class for a game object. To make it scalable, we create a Scale mixin. This is a function, Scale(Base), that returns a new class: class Scaling extends Base { ... }. This Scaling class adds a #scale private field and setScale()/get scale() methods. We then create our final class: const ScalableSprite = Scale(Sprite);. An instance of ScalableSprite now has all the original Sprite features plus the new scaling capabilities. The key footgun is that mixins cannot declare private or protected properties; you must use ES2020 private fields (like #scale) for proper encapsulation.

Interview question

When is using a TypeScript mixin generally preferred over traditional class inheritance?

  • a.To add supplemental, non-essential behaviors to classes across different hierarchies.Correct
  • b.To enforce strict compile-time type checking for all shared functionalities.
  • c.To define the fundamental "is-a" relationship and core identity of a class.
  • d.To create a new base class that serves as a common ancestor for multiple derived classes.
Why?

Mixins are designed to add supplemental, non-essential behaviors to classes that do not share a common inheritance chain, addressing cross-cutting concerns. Traditional inheritance (Option C) is used for defining the core identity and "is-a" relationships, while Option D describes a role for base classes in inheritance, not mixins.

Just read this? Test yourself on what you have been reading.

Read the original → typescriptlang.org

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on typescript — each one lists the topics its interview covers.

See open roles