I'm migrating a functional mixin project from javascript to typescript. All my javascript minxins have constructor signatures with a single parameter constructor(props){}
.
In typescript I have defined a mixin constructor type from following the official docs at https://www.typescriptlang.org/docs/handbook/mixins.html :
export type ConstrainedMixin<T = {}> = new (...args: any[]) => T;
Even if I change that mixin signature to:
export type ConstrainedMixin<T = {}> = new (props: any) => T;
and update the implementations TSC will throw an error:
TS2545: A mixin class must have a constructor with a single rest parameter of type 'any[]'.
This is unfortunate because it doesn't enable creating unique type signatures for the parameters passed to the constructor. I also now need to migrate all my existing constructors. How can I create more explicit type interfaces for the mixin constructors?
I have created a playground example
You can see in this screen shot that the compiler errors on the MIXIN definition and says a mixin class must have a single rest parameter. even though the type definition is:
type ConstrainedMixin<T = {}> = new (props: any) => T;
In the example I have const mg = new MixedGeneric({cool: 'bro'});
I would like to create an interface for that {cool: 'bro'}
object and enforce it from within the mixin definition. I"m not sure how to properly do this. If the constructor is ...args: any[]
Update sounds like this may be some anti pattern so here is further explanation. I am building an entity component system. In my current implementation I have chains of mixins like:
const MixedEntity = RenderMixin(PhysicsMixin(GeometryMixin(Entity));
const entityInstance = new MixedEntity({bunch: "of", props: "that mixins use"});
When the final MixedEntity is instantiated it is passed a props
data bag object. All the Mixins have their own initialization logic in their constructors that looks for specific properties on the props
object.
where my previous mixin classes had constructors like:
constructor(props){
super(props);
if(props.Thing) // do props.thing
}
I now have to migrate the constructors to :
constructor(...args: any[]){
const props = args[0]
super(props);
if(props.Thing) // do props thing
}