Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- type Primitive = string | number;
- type Constructor<T, Args extends any[]> = {
- new (...args: Args): T;
- (...args: Args): T;
- };
- function makeConstructor<
- T,
- Args extends any[],
- P extends Record<string, Primitive | ((this: T) => any)>
- >(create: (...args: Args) => T, prototype?: P) {
- const constructor = function(this: T | undefined, ...args: Args) {
- if (this instanceof constructor) {
- return Object.assign(this, create(...args));
- }
- return new constructor(...args);
- } as Constructor<T & P, Args>;
- constructor.prototype = prototype || {};
- return constructor;
- }
- type CharacterStats = {
- strength: number;
- wisdom: number;
- charisma: number;
- };
- const Character = makeConstructor(
- (characterName: string, stats: CharacterStats) => ({
- // instance
- characterName,
- stats,
- level: 1,
- }),
- {
- // prototype
- __brand: "Character" as const,
- sayHello() {
- console.log(
- "Hi, I'm",
- this.characterName,
- this.level,
- this.stats,
- // **challenge** how to type this without using `class`?
- this.sayHello
- );
- },
- }
- );
- type Character = ReturnType<typeof Character>;
- const merlin = Character("Merlin", { charisma: 6, wisdom: 10, strength: 2 });
- const kingArthur = new Character("King Arthur", {
- charisma: 7,
- strength: 9,
- wisdom: 5,
- });
- merlin.sayHello();
- kingArthur.sayHello();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement