Reputation: 307
Let's say I have a class with many static methods. My goal is to wrap each static method with a function. Specifically, I want to catch async
errors by applying .catch
to each static method like so:
// In user-response.ts
const catchAsyncError = (func: Function) => {
const catcher = (req: Request, res: Response, next: NextFunction) => {
func(req, res, next).catch(next);
}
return catcher;
}
class UserResponse {
static createUser = catchAsyncError(createUser);
static updateUser = catchAsyncError(updateUser);
static deleteUser = catchAsyncError(deleteUser);
// more static methods...
}
// In routes.ts
const router = express.Router();
router.post('/create-user', UserResponse.createUser);
router.patch('/update-user', UserResponse.updateUser);
router.delete('/delete-user', UserResponse.deleteUser);
The overarching goal of doing this is to avoid code repetition. Notice how I have to write catchAsyncError(...)
repeatedly for each static method.
Also, the purpose of placing these functions in a class is to add some semantic context to each function. This way, a developer who is not familiar with the implementation of the various user
related functions will know that they are related because they will read UserResponse.createUser
instead of createUser
.
I'm looking for a solution like this:
// In user-response.ts
const catchAsyncError = (func: Function) => {
const catcher = (req: Request, res: Response, next: NextFunction) => {
func(req, res, next).catch(next);
}
return catcher;
}
@withCatchAsyncError
class UserResponse {
static createUser = createUser;
static updateUser = updateUser;
static deleteUser = deleteUser;
// more static methods...
}
How would I go about implementing a solution like this? Hopefully it's possible, for it is far more elegant and aesthetic than the former.
Upvotes: 1
Views: 539
Reputation: 2099
Your withCatchAsyncError
class decorator will be getting the class constructor at runtime without detailed type information on it. Static class members are actually properties of the constructor, so the decorator will need to go through the constructor's properties, look for those that are themselves functions, and wrap them with catchAsyncError
. Something like this:
function withCatchAsyncError(constructor: Function) {
for (const key of Object.keys(constructor)) {
if (typeof constructor[key] === 'function') {
constructor[key] = catchAsyncError(constructor[key]);
}
}
}
Upvotes: 2