Skip to content

Instantly share code, notes, and snippets.

@rumkin
Last active November 13, 2020 03:55
Show Gist options
  • Save rumkin/281c279c15e8d07352b8f1353a59150b to your computer and use it in GitHub Desktop.
Save rumkin/281c279c15e8d07352b8f1353a59150b to your computer and use it in GitHub Desktop.
Mix methods into a type
type AbstractConstructorHelper<T> = (new (...args: any) => {}) & T;
type Extension = Record<string, {[key in 'method']: unknown}>
type Schematic<T extends Extension> = {
-readonly [K in keyof T]: T[K]['method']
}
type Mixin<T, S extends Extension> = (new (...args: ConstructorParameters<AbstractConstructorHelper<T>>) => InstanceType<AbstractConstructorHelper<T>> & Schematic<S>) & T;
function mixin<T, S extends Extension>(target: T, methods: S): Mixin<T, S> {
// Logic to mix methods in target goes here
return (target as unknown) as (Mixin<T, S>)
}
class Geometry {
width: number = 0
height: number = 0
constructor(width: number, height: number) {
this.width = width
this.height = height
}
}
const methods = {
square: {
method(this: Geometry): number {
return this.width * this.height
},
}
}
const Rectangle = mixin(Geometry, methods)
const rect = new Rectangle(100, 200)
console.log(rect.square())
@rumkin
Copy link
Author

rumkin commented Oct 20, 2020

AbstractConstructorHelper got from this comment: microsoft/TypeScript#31278 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment