Javascript - 创建自定义错误并确保构造函数参数有效

Javascript - Create custom errors and make sure that constructor params are valid

我定义了以下对象

const AuthErrorCode = {
   EMAIL_ALREADY_EXISTS: {
      code: "auth/email-already-exists",
      message: "Hello world!"
   },
   ... more error codes
};

我正在实施一个扩展错误

的class
class AuthError extends Error {
  constructor(code, message = undefined) {
    switch(code) {
      case "EMAIL_ALREADY_EXISTS":
        code = AuthErrorCode[code].code;
        message = message ?? AuthErrorCode[code].message;
        break;

      default:
        throw new Error("Invalid code");
    }

    super(message); 

    Object.assign(this, {
      code,
      name: "AuthError",
    });
  }
}

应该会收到代码和可选的自定义消息。

此 class 必须检查给定代码是否在 AuthErrorCode 对象中(EMAIL_ALREADY_EXISTS || “auth/email-already-exists”有效)。如果它不在其中,那么应该向程序员显示某种反馈(错误或其他)。我的意思是,我需要确保该代码是有效的 AuthErrorCode,因为如果不是,则 class 使用不正确。

我该怎么做?可能吗?

例如,这段代码一定会失败:

throw new AuthError("auth/some-invented-code", "Hello world!");

正确使用示例:

throw new AuthError("EMAIL_ALREADY_EXISTS", "Hello world!");
throw new AuthError("auth/email-already-exists");

有办法,但最终我认为这是糟糕的设计。

如果您已经知道有效值的集合,为什么不简单地公开每种错误类型的工厂函数?

例如

// Assume encapsulated in a module

class AuthError extends Error {
  constructor(message, code) {
    super(message);
    this.code = code;
  }
}

// This would get exported (factory methods for errors)
const authErrors = Object.freeze({
  emailAlreadyExists(message = 'Hello world!') {
    return new AuthError('auth/email-already-exists', message);
  }

   // other error types
});

// Client usage
throw authErrors.emailAlreadyExists('email already registered');

或者,您可以为每个错误类型创建一个显式异常 class,这可能更符合开闭原则:

// Assume encapsulated in a module

class AuthError extends Error {
  constructor(message, code) {
    super(message);
    this.code = code;
  }
}

// Export this
class EmailAdreadyExists extends AuthError {
  constructor(message = "Hello world!") {
    super(message, "auth/email-already-exists");
  }
}

// Client usage
throw new EmailAdreadyExists("email already registered");