macroable
Version:
A simple ES6 class that can be extended to provide macros and getters functionality
105 lines (104 loc) • 3.4 kB
TypeScript
/**
* Shape of the Macro function
*/
declare type MacroFn<T, Args extends any[], ReturnValue extends any> = (this: T, ...args: Args) => ReturnValue;
/**
* Shape of the Getter function
*/
declare type GetterFn<T, ReturnValue extends any> = (this: T) => ReturnValue;
/**
* Returns the typed variation of the macro by inspecting the
* interface declaration
*/
declare 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>;
/**
* Returns the typed variation of the getter by inspecting the
* interface declaration
*/
declare type GetGetterFn<T, K> = K extends keyof T ? GetterFn<T, T[K]> : GetterFn<T, any>;
/**
* Shape of the macroable constructor
*/
export interface MacroableConstructorContract<T extends any> {
macro<K extends string>(name: K, callback: GetMacroFn<T, K>): void;
getter<K extends string>(name: K, callback: GetGetterFn<T, K>, singleton?: boolean): void;
hydrate(): void;
}
/**
* Macroable is an abstract class to add ability to extend your class
* prototype using better syntax.
*
* Macroable has handful of benefits over using traditional `prototype` approach.
*
* 1. Methods or properties added dynamically to the class can be removed using `hydrate` method.
* 2. Can define singleton getters.
*/
export declare abstract class Macroable {
protected static macros: {
[key: string]: MacroFn<any, any[], any>;
};
protected static getters: {
[key: string]: GetterFn<any, any>;
};
constructor();
/**
* Add a macro to the class. This method is a better to manually adding
* to `class.prototype.method`.
*
* Also macros added using `Macroable.macro` can be cleared anytime
*
* @example
* ```js
* Macroable.macro('getUsername', function () {
* return 'virk'
* })
* ```
*/
static macro<T extends any, K extends string>(this: {
new (...args: any): T;
}, name: string, callback: GetMacroFn<T, K>): void;
/**
* Return the existing macro or null if it doesn't exists
*/
static getMacro(name: string): MacroFn<any, any[], any> | undefined;
/**
* Returns a boolean telling if a macro exists
*/
static hasMacro(name: string): boolean;
/**
* Define a getter, which is invoked everytime the value is accessed. This method
* also allows adding single getters, whose value is cached after first time
*
* @example
* ```js
* Macroable.getter('time', function () {
* return new Date().getTime()
* })
*
* console.log(new Macroable().time)
*
* // Singletons
* Macroable.getter('time', function () {
* return new Date().getTime()
* }, true)
*
* console.log(new Macroable().time)
* ```
*/
static getter<T extends any, K extends string>(this: {
new (...args: any): T;
}, name: string, callback: GetGetterFn<T, K>, singleton?: boolean): void;
/**
* Return the existing getter or null if it doesn't exists
*/
static getGetter(name: string): GetterFn<any, any> | undefined;
/**
* Returns a boolean telling if a getter exists
*/
static hasGetter(name: string): boolean;
/**
* Cleanup getters and macros from the class
*/
static hydrate(): void;
}
export {};