Not to be confused with Typescript mixins https://www.typescriptlang.org/docs/handbook/mixins.html
I am trying to create type definition files for my JS project which heavily uses mixins. These type definition files would normally be generated from JSDocs syntax by TSC (using allowJs/checkJs feature), but for mixins this is impossible, so I type them by hand.
I am not sure what the right way to do this is, but I've given it a good attempt so far. However, my static properties/methods are not properly inherited/type hinted.
interface StringToFunctionMap {
[key: string]: Function;
}
declare type Constructor<T> = new (...args: any[]) => T;
declare class LocalizeMixinHost {
public static get localizeNamespaces(): StringToFunctionMap[];
public static someStaticObjArr(): StringToFunctionMap[];
public someObjArr(): StringToFunctionMap[];
public onLocaleReady(): void;
}
declare function LocalizeMixinImplementation<T extends Constructor<HTMLElement>>(
superclass: T,
): T & Constructor<LocalizeMixinHost>;
declare type LocalizeMixin = typeof LocalizeMixinImplementation;
const LocalizeMixin: LocalizeMixin = (superclass) =>
class LocalizeMixin extends superclass {
static get localizeNamespaces() {
return [{ 'foo': () => { } }];
}
static someStaticObjArr() {
return [{ 'foo': () => { } }];
}
someObjArr() {
return [{ 'foo': () => { } }];
}
onLocaleReady() {
// do something
}
}
class MyElement extends LocalizeMixin(HTMLElement) {
static get localizeNamespaces() {
return [{ 'bar': () => { }}, ...super.localizeNamespaces];
}
static someStaticObjArr() {
return [{ 'bar': () => { }}, ...super.someStaticObjArr()]
}
someObjArr() {
return [{ 'bar': () => { }}, ...super.someObjArr()]
}
onLocaleReady() {
super.onLocaleReady();
}
}
As you may be able to see, it works pretty nicely for my methods, unless they are static. This is probably because the Constructor type won't carry over the static parts. So I tried changing the LocalizeMixinImplementation to also intersect the type of the class itself by doing:
declare function LocalizeMixinImplementation<T extends Constructor<HTMLElement>>(
superclass: T,
): T & Constructor<LocalizeMixinHost> & typeof LocalizeMixinHost;
This seems to work for the static parts, but now I get an error on LocalizeMixin(HTMLElement) --> 'Base Constructors must all have the same return type'. I am pretty lost now, I don't understand what the error means at all. What does it mean by Base Constructor specifically? What does it mean with same return type, specifically?