Skip to content

Instantly share code, notes, and snippets.

@NoelDeMartin
Last active April 29, 2024 10:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save NoelDeMartin/16c4d390e7c310d0387761f9b561f102 to your computer and use it in GitHub Desktop.
Save NoelDeMartin/16c4d390e7c310d0387761f9b561f102 to your computer and use it in GitHub Desktop.
Laravel's tap helper implementation in Javascript & Typescript

I recently added this code to my utils package, so you are welcome to use it you want this. It's tree-shakable, so you don't have to worry about everything else!

// Javascript equivalent of Laravel's tap helper method
// @see https://medium.com/@taylorotwell/tap-tap-tap-1fc6fc1f93a6
// @see https://github.com/laravel/framework/blob/v7.8.0/src/Illuminate/Support/helpers.php#L422..L431
export function proxyTap(target) {
const proxy = new Proxy(target, {
get(target, key, receiver) {
const prop = Reflect.get(target, key, receiver);
if (typeof prop !== 'function')
return prop;
return (...params) => {
prop.call(target, ...params);
return proxy;
};
},
});
return proxy;
}
export function tap(target, callback) {
if (!callback)
return proxyTap(target);
callback(target);
return target;
}
// Typescript equivalent of Laravel's tap helper method
// @see https://medium.com/@taylorotwell/tap-tap-tap-1fc6fc1f93a6
// @see https://github.com/laravel/framework/blob/v7.8.0/src/Illuminate/Support/helpers.php#L422..L431
type Tapped<Target extends object> = {
[prop in keyof Target]: Target[prop] extends (...params: infer Params) => any
? (...params: Params) => Tapped<Target>
: Target[prop];
}
export function proxyTap<Target extends object>(target: Target): Tapped<Target> {
const proxy = new Proxy(target, {
get(target: object, key: PropertyKey, receiver?: any) {
const prop = Reflect.get(target, key, receiver);
if (typeof prop !== 'function')
return prop;
return (...params: any[]) => {
prop.call(target, ...params);
return proxy;
};
},
}) as Tapped<Target>;
return proxy;
}
export function tap<Target extends object>(target: Target): Tapped<Target>;
export function tap<Target extends object>(target: Target, callback: (target: Target) => any): Target;
export function tap<Target extends object>(
target: Target,
callback?: (target: Target) => any,
): Target | Tapped<Target> {
if (!callback)
return proxyTap(target);
callback(target);
return target;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment