Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ES6 Mixin with generic type in TypeScript

I'm trying to use ES6 Mixin in TypeScript. What I have is as below, and it works perfect with BaseClass.

class BaseClass {
    public foo() {}
};

interface IMyMixin {
    foo2();
}

let MyMixin = (superclass: typeof BaseClass) => class extends BaseClass implements IMyMixin {
    public foo2() {}
}

class MyBaseClass extends MyMixin(BaseClass) {

}

However I can't apply MyMixin on derived class from BaseClass; Meanwhile, I can't make mixin generic either.

Is there a way to make it work for both BaseClass and DerivedClass?

class DerivedClass extends BaseClass {
    public bar() {}
}

class MyDerivedClass extends MyMixin(DerivedClass) {
    public something() {
// Compile Error: Property 'bar' does not exist on type 'MyDerivedClass'
        this.bar();
    }
}

// Compile Error: 'T' only refers to a type, but is being used as a value here.
let MyMixin = <T extends BaseClass>(superclass: typeof T) => class extends T implements IMyMixin {
    public foo2() {}
}
like image 759
Haocheng Avatar asked Oct 30 '22 10:10

Haocheng


1 Answers

I've found solution from TypeScript/PR#13743, and optimized it with comment from @Maximus.

This piece of code works. The reason is, in MyMixin, T should be a Class (i.e. a constructor), not a type.

type Constructor<T> = new (...args: any[]) => T;

class BaseClass {
    public foo() { }
};

interface IMyMixin {
    foo2();
}

// `implements IMyMixin` is optional.
let MyMixin = <T extends Constructor<BaseClass>>(superclass: T) => class extends superclass implements IMyMixin {
    public foo2() { }
}

class DerivedClass extends BaseClass {
    public bar() {}
}

class MyDerivedClass extends MyMixin(DerivedClass) {
    public something() {
        this.bar();
        this.foo();
        this.foo2();
    }
}
like image 68
Haocheng Avatar answered Nov 16 '22 11:11

Haocheng