Typescript definition for ES6 mixins

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

I have this template in library.js and I would like to create library.d.ts

 // 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) {} 
+5
source share
1 answer

No, a system like Typescript is not expressive enough for this - see the discussion at https://github.com/Microsoft/TypeScript/issues/7225 and https://github.com/Microsoft/TypeScript/issues/4890 .

The idiomatic "class type" in Typescript is written as

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

So one way to write a 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, the return type of the Compose type is declared by the constructor for the intersection type - the type that must have all the properties of the (Base) parameter along with all the mixin properties.

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

 import {Super} from './library' let MyComposed = Super.Compose(Super) let myInstance = new MyComposed 

The slight inconvenience is that you always need to provide an argument for Super.Compose (), because type inference does not work without knowing the value for the default parameter, and you cannot specify the default parameter value in the declaration file.

But the big problem is that you cannot use the Compose result as a class:

 class MyClass extends Super.Compose(Super) {} 

does not compile due to the problems mentioned above:

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

All Articles