Skip to content

Instantly share code, notes, and snippets.

@disco0
Created December 18, 2020 12:08
Show Gist options
  • Save disco0/7d637e52a1dd8c18f18ca11d703d184e to your computer and use it in GitHub Desktop.
Save disco0/7d637e52a1dd8c18f18ca11d703d184e to your computer and use it in GitHub Desktop.
TypeScript - Callable Constructor Wrapper
const samples: any[] = [];
//#region Components
class Point2DClass
{
constructor(public x: number, public y: number) { }
toString(): string { return `x: ${this.x}\ny: ${this.y}` }
}
function Point2DConstructor(this: Point2DClass | undefined | void, ...args: ConstructorParameters<typeof Point2DClass>)
{
return new Point2DClass(args[0], args[1]);
}
//#endregion Components
//#region Programmatic
function CallableConstructor<A extends any[], B extends {(...args: A): I}, C extends {new(...args: A): I}, I>(Class: C, Constructor: B): B & C
{
return Object.assign(
Constructor,
Class, {
[Symbol.species]: Class,
get[Symbol.toStringTag](){ return Class.name },
}
)
}
{
const Point2D = CallableConstructor(Point2DClass, Point2DConstructor);
samples.push(Point2D)
}
//#endregion Programmatic
//#region Manual Implementation
const Point2DMerge: typeof Point2DConstructor& typeof Point2DClass
= Object.assign(Point2DConstructor, Point2DClass);
samples.push(Point2DMerge)
//#endregion Manual Implementation
//#region Testing
function test<C, B extends {new (x: number, y: number): C; (x: number, y: number): C}>(TestCallableConstructor: B): void
{
console.log(`Testing object: %o`, TestCallableConstructor)
console.log(`As string %s`, TestCallableConstructor)
const callX = TestCallableConstructor(3,4);
const newX = new TestCallableConstructor(4,5);
console.log(`${callX}`);
console.log(`${newX}`);
}
var run = () => samples.forEach(test);
//#endregion Testing
run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment