Advertisement
Guest User

Untitled

a guest
Jun 20th, 2019
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.36 KB | None | 0 0
  1. type Primitive = string | number;
  2.  
  3. type Constructor<T, Args extends any[]> = {
  4. new (...args: Args): T;
  5. (...args: Args): T;
  6. };
  7.  
  8. function makeConstructor<
  9. T,
  10. Args extends any[],
  11. P extends Record<string, Primitive | ((this: T) => any)>
  12. >(create: (...args: Args) => T, prototype?: P) {
  13. const constructor = function(this: T | undefined, ...args: Args) {
  14. if (this instanceof constructor) {
  15. return Object.assign(this, create(...args));
  16. }
  17. return new constructor(...args);
  18. } as Constructor<T & P, Args>;
  19.  
  20. constructor.prototype = prototype || {};
  21. return constructor;
  22. }
  23.  
  24. type CharacterStats = {
  25. strength: number;
  26. wisdom: number;
  27. charisma: number;
  28. };
  29.  
  30. const Character = makeConstructor(
  31. (characterName: string, stats: CharacterStats) => ({
  32. // instance
  33. characterName,
  34. stats,
  35. level: 1,
  36. }),
  37. {
  38. // prototype
  39. __brand: "Character" as const,
  40. sayHello() {
  41. console.log(
  42. "Hi, I'm",
  43. this.characterName,
  44. this.level,
  45. this.stats,
  46. // **challenge** how to type this without using `class`?
  47. this.sayHello
  48. );
  49. },
  50. }
  51. );
  52.  
  53. type Character = ReturnType<typeof Character>;
  54.  
  55. const merlin = Character("Merlin", { charisma: 6, wisdom: 10, strength: 2 });
  56. const kingArthur = new Character("King Arthur", {
  57. charisma: 7,
  58. strength: 9,
  59. wisdom: 5,
  60. });
  61.  
  62. merlin.sayHello();
  63. kingArthur.sayHello();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement