// Utility types:
type GetProps<TBase> = TBase extends new (props: infer P) => any ? P : never
type GetInstance<TBase> = TBase extends new (...args: any[]) => infer I ? I : never
type MergeCtor<A, B> = new (props: GetProps<A> & GetProps<B>) => GetInstance<A> & GetInstance<B>
// Usage:
// bypass the restriction and manually type the signature
function GeometryMixin<TBase extends MixinBase>(Base: TBase) {
// key 1: assert Base as any to mute the TS error
const Derived = class Geometry extends (Base as any) {
shape: 'rectangle' | 'triangle'
constructor(props: { shape: 'rectangle' | 'triangle' }) {
super(props)
this.shape = props.shape
}
}
// key 2: manually cast type to be MergeCtor
return Derived as MergeCtor<typeof Derived, TBase>
}