TypeScript decorators are functions that wrap and augment classes, methods, or properties:
function Log(target: unknown, key: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = function (...args: unknown[]) {
console.log(`[${key}] called with`, args);
return original.apply(this, args);
};
return descriptor;
}
class UserService {
@Log
getUser(id: string) { /* ... */ }
}The same pattern works as plain higher-order functions — which is the approach here (Judge0 doesn't need the @ syntax).
Implement three method-wrapping utilities:
| Utility | Behaviour |
|---|---|
memoizeMethod(fn) | Cache results by stringified args — same args → same result, no re-execution |
logMethod(fn, name) | Push "[name] called with [args]" to callLog before each call |
retryMethod(fn, n) | Retry up to n times on error before re-throwing |
Sample tests