如何在 Typescript 中使用 Class 装饰器来修改所有 Classes 的静态方法?
How to use a Class Decorator in Typescript to modify all of the Classes' Static Methods?
假设我有一个包含许多静态方法的 class。我的目标是用一个函数包装每个静态方法。具体来说,我想通过将 .catch
应用于每个静态方法来捕获 async
错误,如下所示:
// 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);
这样做的首要目标是避免代码重复。请注意我必须如何为每个静态方法重复编写 catchAsyncError(...)
。
此外,将这些函数放在一个 class 中的目的是为每个函数添加一些语义上下文。这样,不熟悉各种 user
相关函数实现的开发人员就会知道它们是相关的,因为他们会读到 UserResponse.createUser
而不是 createUser
。
我正在寻找这样的解决方案:
// 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...
}
我将如何着手实施这样的解决方案?希望这是可能的,因为它比前者更加优雅和美观。
您的 withCatchAsyncError
class 装饰器将在运行时获取 class 构造函数,但没有详细的类型信息。静态 class 成员实际上是构造函数的属性,所以装饰器需要遍历构造函数的属性,寻找那些本身就是函数的,然后用 catchAsyncError
包装它们。像这样:
function withCatchAsyncError(constructor: Function) {
for (const key of Object.keys(constructor)) {
if (typeof constructor[key] === 'function') {
constructor[key] = catchAsyncError(constructor[key]);
}
}
}
假设我有一个包含许多静态方法的 class。我的目标是用一个函数包装每个静态方法。具体来说,我想通过将 .catch
应用于每个静态方法来捕获 async
错误,如下所示:
// 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);
这样做的首要目标是避免代码重复。请注意我必须如何为每个静态方法重复编写 catchAsyncError(...)
。
此外,将这些函数放在一个 class 中的目的是为每个函数添加一些语义上下文。这样,不熟悉各种 user
相关函数实现的开发人员就会知道它们是相关的,因为他们会读到 UserResponse.createUser
而不是 createUser
。
我正在寻找这样的解决方案:
// 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...
}
我将如何着手实施这样的解决方案?希望这是可能的,因为它比前者更加优雅和美观。
您的 withCatchAsyncError
class 装饰器将在运行时获取 class 构造函数,但没有详细的类型信息。静态 class 成员实际上是构造函数的属性,所以装饰器需要遍历构造函数的属性,寻找那些本身就是函数的,然后用 catchAsyncError
包装它们。像这样:
function withCatchAsyncError(constructor: Function) {
for (const key of Object.keys(constructor)) {
if (typeof constructor[key] === 'function') {
constructor[key] = catchAsyncError(constructor[key]);
}
}
}