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 & {}> }
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.
source share