A better type inference for class mixins in TypeScript 3.x

Anton Golub
2 min readJan 22, 2020

--

This note demonstrates the way of how to avoid manual types declaration when classes are combined by mixing.

Mixin is a well-known technique which compensates the lack of built-in multiple inheritance in TS/JS. This is partly a workaround, but everything is good enough with typings as long as we adhere functional mixins or sub-class factories patterns. However if we need to merge several unrelated classes (directed acyclic graph, you know), type inference might be slightly complicated for tsc and we have to describe the result type by hand.

The problem can be illustrated by a code snippet from the official TS documentation:

This implementation skips constructor invocation step (which may assign own instance fields) and does not inherit static methods, which could also be referenced in prototype and so on. Never mind, it’s easy to fix:

But tsc still does not recognise what happens inside. Let’s take a closer look. Once we declare a new class, TS creates an interface with the same name.

This interface describes instance type only, but not the class itself, which actually is something like:

Fortunately, there’s a special utility type InstanceType<T> and we’re able to get instance type by a class reference inside applyMixins context. Further task is quite simple.

Since TS 3.0 rest parameter of function is permitted to have a generic type. So it’s also possible to adapt mixin applier signature for an arbitrary number of arguments through UnionToIntersection<U> type transformation and array values types extraction. As a result, we have:

Works like a charm. Consistent and predictable merger with correct IDE hints.

Full code and tests: https://github.com/qiwi/mixin

--

--