UNPKG

3.4 kBTypeScriptView Raw
1/**
2 * Shape of the Macro function
3 */
4declare type MacroFn<T, Args extends any[], ReturnValue extends any> = (this: T, ...args: Args) => ReturnValue;
5/**
6 * Shape of the Getter function
7 */
8declare type GetterFn<T, ReturnValue extends any> = (this: T) => ReturnValue;
9/**
10 * Returns the typed variation of the macro by inspecting the
11 * interface declaration
12 */
13declare type GetMacroFn<T, K> = K extends keyof T ? T[K] extends (...args: infer A) => infer B ? MacroFn<T, A, B> : MacroFn<T, any[], any> : MacroFn<T, any[], any>;
14/**
15 * Returns the typed variation of the getter by inspecting the
16 * interface declaration
17 */
18declare type GetGetterFn<T, K> = K extends keyof T ? GetterFn<T, T[K]> : GetterFn<T, any>;
19/**
20 * Shape of the macroable constructor
21 */
22export interface MacroableConstructorContract<T extends any> {
23 macro<K extends string>(name: K, callback: GetMacroFn<T, K>): void;
24 getter<K extends string>(name: K, callback: GetGetterFn<T, K>, singleton?: boolean): void;
25 hydrate(): void;
26}
27/**
28 * Macroable is an abstract class to add ability to extend your class
29 * prototype using better syntax.
30 *
31 * Macroable has handful of benefits over using traditional `prototype` approach.
32 *
33 * 1. Methods or properties added dynamically to the class can be removed using `hydrate` method.
34 * 2. Can define singleton getters.
35 */
36export declare abstract class Macroable {
37 protected static macros: {
38 [key: string]: MacroFn<any, any[], any>;
39 };
40 protected static getters: {
41 [key: string]: GetterFn<any, any>;
42 };
43 constructor();
44 /**
45 * Add a macro to the class. This method is a better to manually adding
46 * to `class.prototype.method`.
47 *
48 * Also macros added using `Macroable.macro` can be cleared anytime
49 *
50 * @example
51 * ```js
52 * Macroable.macro('getUsername', function () {
53 * return 'virk'
54 * })
55 * ```
56 */
57 static macro<T extends any, K extends string>(this: {
58 new (...args: any): T;
59 }, name: string, callback: GetMacroFn<T, K>): void;
60 /**
61 * Return the existing macro or null if it doesn't exists
62 */
63 static getMacro(name: string): MacroFn<any, any[], any> | undefined;
64 /**
65 * Returns a boolean telling if a macro exists
66 */
67 static hasMacro(name: string): boolean;
68 /**
69 * Define a getter, which is invoked everytime the value is accessed. This method
70 * also allows adding single getters, whose value is cached after first time
71 *
72 * @example
73 * ```js
74 * Macroable.getter('time', function () {
75 * return new Date().getTime()
76 * })
77 *
78 * console.log(new Macroable().time)
79 *
80 * // Singletons
81 * Macroable.getter('time', function () {
82 * return new Date().getTime()
83 * }, true)
84 *
85 * console.log(new Macroable().time)
86 * ```
87 */
88 static getter<T extends any, K extends string>(this: {
89 new (...args: any): T;
90 }, name: string, callback: GetGetterFn<T, K>, singleton?: boolean): void;
91 /**
92 * Return the existing getter or null if it doesn't exists
93 */
94 static getGetter(name: string): GetterFn<any, any> | undefined;
95 /**
96 * Returns a boolean telling if a getter exists
97 */
98 static hasGetter(name: string): boolean;
99 /**
100 * Cleanup getters and macros from the class
101 */
102 static hydrate(): void;
103}
104export {};