Skip to content

Instantly share code, notes, and snippets.

@Offirmo
Last active February 18, 2022 11:58
Show Gist options
  • Save Offirmo/ac5c952932b846cfe8093652d499de41 to your computer and use it in GitHub Desktop.
Save Offirmo/ac5c952932b846cfe8093652d499de41 to your computer and use it in GitHub Desktop.
[proxy function in TypeScript] #tags: TypeScript
/**
* Conveniently proxy functions instead of storing the value and applying it yourself.
*
* proxyFunction(someApiFunction, (args, callOriginalFunction) => {
* if (whateverYouWant) {
* return 'custom value'
* // Never call the original
* }
*
*
* // Call original function with custom arguments
* callOriginalFunction('foo', 'bar')
*
* // Or with original arguments
* return callOriginalFunction(...args)
* }
*
* // proxyMethod is the same, but with no worries about the stupid ‘this’:
* proxyMethod(console, 'log', (args, callOriginalFunction) =>
* yourCondition ? '' : callOriginalFunction(custom, arg))
*/
interface ProxyCallback<F extends Function> {
(args: any[], callOriginal: F): any
}
export const proxyFunction = <F extends Function>(f: F, proxy: ProxyCallback<F>, context: Object = null): F =>
// Note on the internals of typing in this function.
// ProxyCallback is <Args => Result>(args: Args, original: Args=>Result): Result,
// (pseudo-syntax), but we can not express it in TypeScript 1.7.
// We can parametrize on Result alone, and this typechecks in TypeScript 1.7,
// but it requires arguments to be any[].
// Current solution keeps the outer types correct for callers
// at the cost of weaker implementation.
((...args: any[]) =>
proxy(args, ((...newArgs: any[]) => f.apply(context, newArgs)) as any)) as any
export const proxyMethod = (object: Object, method: string, proxy: ProxyCallback<any>) => {
object[method] = proxyFunction(object[method], proxy, object)
}
export default proxyFunction
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment