I am working with the code snippet shown below:
// Types found on https://stackoverflow.com/a/55468194
type Constructor<T = {}> = new (...args: any[]) => T;
/* turns A | B | C into A & B & C */
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ( k: infer I ) => void ? I : never;
/* merges constructor types - self explanitory */
type MergeConstructorTypes<T extends Array<Constructor<any>>> = UnionToIntersection<InstanceType<T[number]>>;
var Mixin = function <T extends Constructor[]>(
...mixins: T
): Constructor<MergeConstructorTypes<T>> {
const MixinSuperClass: Constructor<MergeConstructorTypes<T>> = class {
} as Constructor<MergeConstructorTypes<T>>;
return MixinSuperClass;
};
type all = "all1" | "all2";
class ClassA<T extends string = all | "a1" | "a2"> {
hopa(p: T | all) {
return 'a' + p;
}
}
class ClassB {
hopb(p: all) {
return 'b' + p;
}
}
class ClassOK extends Mixin(ClassA<"aa">, ClassB) { }
const c = new ClassOK;
c.hopa("aa"); // the "aa" value has been autocompleted
class ClassKO<T extends string = ""> extends Mixin(ClassA<T>, ClassB) { } // Just notice that Mixin is not limited to only 2 args
class ClassFinal extends ClassKO<"aaa"> {}
const d = new ClassKO<"a" | "b">;
d.hopa("aa"); // here there was no autocomplete while I would like to have "aa"
const de = new ClassFinal;
de.hopa("aaa"); // here there was no autocomplete while I would like to have "aaa"
Mixin
is a custom function designed to provide typing for ClassOk
. To streamline it, certain functional aspects were removed making the code inoperable. The key task at hand is to enable auto-completion of values when invoking de.hopa("
, based on the extension of
ClassFinal which extends ClassKO<"aaa">
.
The main challenge lies in defining the Mixin function with generic types...
For a more interactive experience, visit this Playground Link