Search code examples
typescriptwebpackmixinses6-modules

ES6-Exporting classes with typescript mixins


I encounter a puzzling problem when composing a complexe class hierarchy, each class being exported from separate ES6-modules-like files, with mixins involved.

Here's a simplified exemple reproducing my problem:

File "mixinA.ts":

type Constructor = new (...args: any[]) => {};

export default function addMixinA<TBase extends Constructor>(Base: TBase) {
    return class MixedInA extends Base {
        public prop1 = 1
    }
}

File "classB.ts":

import addMixinA from "./mixinA"

class ClassB {
    public prop2 = 2
}

let ClassB_WithMixin = addMixinA(ClassB)
export default ClassB_WithMixin

File "classC.ts":

import classB from "./classB"

class ClassC {

    // 'classB' refers to a value, but is being used as a type here. Did you mean 'typeof classB'? ts(2749)
    public classB_instance: classB
}

As you can see in the comment I added above the faulting line, an error is produced in the file classC.ts when using the export from classA.ts.

Am I doing something wrong? Can you spot my error?


Solution

  • Congratulations on your first post!

    Try this:

    class ClassC {
        public classB_instance: InstanceType<typeof classB> = new classB()
    }
    

    You cannot annotate a field by using classB, because classB is not a type. It's a value. To use the type of this value, the typeof operator is needed (type Foo = typeof classB).

    Alternatively, do this:

    class ClassB_WithMixin extends addMixinA(ClassB) {}
    
    class ClassC {
    
        public classB_instance: ClassB_WithMixin = new ClassB_WithMixin()
    }
    

    This difference here is that instead of doing assignment (let ClassB_WithMixin = addMixinA(ClassB)), we're doing inheritance (class ClassB_WithMixin extends addMixinA(ClassB) {}) which produces a real class. And classes in TypeScript are both types and values.