Skip to content

Instantly share code, notes, and snippets.

@HighLiuk
Last active January 3, 2024 11:24
Show Gist options
  • Save HighLiuk/89bd39cc0b01760bddb8a98d5a395167 to your computer and use it in GitHub Desktop.
Save HighLiuk/89bd39cc0b01760bddb8a98d5a395167 to your computer and use it in GitHub Desktop.
WP Hooks with TypeScript
type Events = {
hook_1: string[];
hook_2: number;
};
const { addFilter, applyFilters } = new Filter<Events>();
addFilter('hook_1', callback)
// ^ autocomplete on event names
// ^ static analysis on callback functions based on the specific event
function callback(list: string[]): string[] {
if (list.length === 0) {
return ['default'];
}
return list;
}
// ...
const list = applyFilters('hook_1', []);
console.log(list)
// ^ ['default']
/**
* A function type that takes a parameter of type T and returns a value of type T.
*/
type FilterFunction<T = any> = (data: T) => T;
/**
* A class that represents a filter system. It maintains a list of filter functions for
* each event. E is a record of event names to their data types.
*/
export class Filter<E extends Record<string, any>> {
/**
* A record of filter functions for each event. The keys are event names and the
* values are arrays of filter functions.
*/
protected filters = {} as Record<keyof E, FilterFunction[]>;
public constructor() {
// allow destructuring of the methods
this.addFilter = this.addFilter.bind(this);
this.applyFilters = this.applyFilters.bind(this);
}
/**
* Adds a filter function to a specific event.
*
* @param event - The name of the event.
* @param cb - The filter function to add.
*/
public addFilter<T extends keyof E>(event: T, cb: FilterFunction<E[T]>) {
if (!this.filters[event]) {
this.filters[event] = [];
}
this.filters[event].push(cb);
}
/**
* Applies the filter functions to the data of a specific event. If no filter
* functions are added to the event, the original data is returned.
*
* @param event - The name of the event.
* @param data - The data to apply the filter functions to.
* @returns The data after applying the filter functions.
*/
public applyFilters<T extends keyof E>(event: T, data: E[T]): E[T] {
if (!this.filters[event]) {
return data;
}
return this.filters[event].reduce((value, cb) => cb(value), data);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment