mirror of
https://github.com/arthur-pbty/portfolio2023.git
synced 2026-06-03 23:36:21 +02:00
105 lines
3.3 KiB
TypeScript
105 lines
3.3 KiB
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 {};
|