如何在 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]);
    }
  }
}