Description
Following the great mixin implementation by @ahejlsberg (#13743)
Having a mixin function returns a class is powerful but requires manual type declaration.
interface Tagged {
_tag: string;
}
class Point {
constructor(public x: number, public y: number) {}
}
type Constructor<T> = new(...args: any[]) => T;
function Tagged<T extends Constructor<{}>>(Base: T) {
return class extends Base {
_tag: string;
constructor(...args: any[]) {
super(...args);
this._tag = "";
}
}
}
export const TaggedPoint: Constructor<Tagged> & typeof Point = Tagged(Point);
const tPoint: TaggedPoint; // ERROR: Cannot find name 'TaggedPoint'
We can't use TaggedPoint
as a type, unless we:
export type TaggedPoint = Constructor<Tagged> & typeof Point;
const tPoint: TaggedPoint; // NOW OK
Using classes we can
export class Customer extends Tagged(Person) {
accountBalance: number;
}
Which exposes the type but forces the developer to extend
the Customer
class.
My feature request is allowing:
export class TaggedPoint = Tagged(Point);
Which will be just sugar for:
export const TaggedPoint = Tagged(Point);
export type TaggedPoint = Constructor<Tagged> & typeof Point;
Maybe even:
export class TaggedPoint = Tagged(Point) { // user can extend here...
}
but that's not the main point...
The motivation for this is a more robust mixin mechanism that revolves around the base class and allow mixin's to know about it, using generic it provides powerful combinations.
So I can have
RestMixin(Base, Mixin1, Mixin2);
And the return type can have members from Mixin1 knowning about Base, using interfaces one can even set static members of a mixin to return T which is the instance of RestMixin(Base, Mixin1, Mixin2)
all together.