Skip to content

Instantly share code, notes, and snippets.

@NoTimeForHero
Created February 9, 2024 20:08
Show Gist options
  • Save NoTimeForHero/239d84eec9edae0ecfd63374f6f71cb5 to your computer and use it in GitHub Desktop.
Save NoTimeForHero/239d84eec9edae0ecfd63374f6f71cb5 to your computer and use it in GitHub Desktop.
Замена функции в объекте с полной поддержкой типов
// https://stackoverflow.com/questions/49752151/typescript-keyof-returning-specific-type
type KeyOfType<T, V> = keyof {
[P in keyof T as T[P] extends V ? P : never]: any;
};
type InferArgs<TValueType> = TValueType extends (...args: infer U) => any ? U : never;
type InferReturn<TValueType> = TValueType extends (...args: any) => infer U ? U : never;
const replaceFunction = <
TArgs extends InferArgs<TObject[TKey]>,
TReturn extends InferReturn<TObject[TKey]>,
TCallable extends (...args: any) => any,
TObject extends Record<string, any>,
TKey extends KeyOfType<TObject, TCallable>,
>(
target: TObject,
name: TKey,
callback: (oldFunction: TObject[TKey], ...args: TArgs) => TReturn,
) => {
const oldCallable = target[name];
const newCallable = (...args: TArgs) => callback(oldCallable, ...args);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
target[name] = newCallable as any;
};
// Пример использования
// Перехватываем функцию GET в роутере Express чтобы знать о регистрации нового маршрута
const router = express.Router();
replaceFunction(router, 'get', (prev, path, ...args) => {
console.log('Registered new route: ', path);
return prev.call(router, path, ...args);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment