trefeater trefeater - 11 months ago 56
TypeScript Question

Typescript definition for ES6 mixins

Is there a way to write a Typescript definition for an ES6 mix-in?

I've this pattern in

, and I'd like to create the

// declaration in `library.js`
class Super extends Simple {
constructor() {}

static Compose(Base = Super) {
return class extends Base {
// ...


// usage in `client.js`
class MyClass extends Super.Compose() {}
let myInstance = new MyClass();

class MyOtherClass extends Super.Compose(AnotherClass) {}

Answer Source

No, Typescript type system is not expressive enough for that - see the discussion in and

The idiomatic 'type of classes' in typescript is written as

interface Constructor<T> {
    new (...args): T;

So one way to write declaration for Compose is

export declare class Simple {}

export declare class Super extends Simple {
    static Compose<T>(Base?: Constructor<T>): Constructor<T & {/*mixed-in declarations*/}>

That is, Compose return type is declared to be a constructor for intersection type - a type which must have all the properties of parameter (Base) together with all the properties of the mixin.

You can use that declaration (assuming it's in the library.d.ts file) like this

import {Super} from './library'

let MyComposed = Super.Compose(Super)
let myInstance = new MyComposed

The minor inconvenience is that you always have to provide argument for Super.Compose() because type inference does not work without knowing the value for default parameter, and you can't provide value for default parameter in the declaration file.

But the big problem is that you can't really use the result of Compose as a class:

class MyClass extends Super.Compose(Super) {}

does not compile due to the issues mentioned above:

error TS2509: Base constructor return type 'Super & {}' is not a class or interface type.