The question is basically is how to ensure type-checking with higher-order components implemented in a typical JavaScript way.
Hoc1 = (superclass) => class extends superclass { ... }
class A { ... }
class B extends Hoc1(A) { ... }
By type-checking I mean using any of two most prominent utilities: TypeScript or flow.
So far I have come up with the following snippet in TypeScript,
interface IAMixin {
aMixedMethod(): void
}
interface IAMixinConstructor {
new(): IAMixin
}
const AHoc: <T>(superclass: T) => T & IAMixinConstructor = (superclass) =>
class extends superclass implements IAMixin {
aMixedMethod() {}
}
class A {
aMethod() {}
}
class B extends AHoc(A) {
bMethod() {}
}
const b = new B();
b.aMixedMethod(); // false-positive: incrorrectly reports as missing method
b.aMethod();
b.bMethod();
b.cMethod(); // this is correctly caught, though
If I wrote the mixin this way
const AMixin: (superclass) => typeof superclass & IAMixinConstructor =
(superclass) => class extends superclass implements IAMixin {
aMixedMethod() {}
}
then it thinks of superclass
as any
and false-negatively misses an error with the call of cMethod
.
This seems to be possible at least in TypeScript, cause they have e.g. Object.assign
correctly working for instances. But I need the construction of the same kind, but for classes.
Or do we need class types like Ruby classes?
what was missing was defining the AHoc
parameter as of constructor function type for the class instead of an actual instance and the same for the returned value:
interface IAMixin {
aMixedMethod(): void
}
const AHoc: <T>(superclass: new () => T) => new () => (T & IAMixin) =
(superclass) => class extends superclass implements IAMixin {
aMixedMethod() { }
}
class A {
aMethod() {}
}
class B extends AHoc(A) {
bMethod() {}
}
const b = new B();
b.aMixedMethod(); // now good
b.aMethod();
b.bMethod();
b.cMethod(); // this is correctly caught