web-dev-qa-db-ja.com

switchステートメントでinstanceofを使用する方法

カスタムエラー( es6-error )を使用して、クラスに基づいて次のようにエラーを処理できます。

import { DatabaseEntryNotFoundError, NotAllowedError } from 'customError';

function fooRoute(req, res) {
  doSomethingAsync()
    .then(() => {
      // on resolve / success
      return res.send(200);
    })
    .catch((error) => {
      // on reject / failure
      if (error instanceof DatabaseEntryNotFoundError) {
        return res.send(404);
      } else if (error instanceof NotAllowedError) {
        return res.send(400);
      }
      log('Failed to do something async with an unspecified error: ', error);
      return res.send(500);
    };
}

このタイプのフローにはスイッチを使用したいので、次のような結果になります。

import { DatabaseEntryNotFoundError, NotAllowedError } from 'customError';

function fooRoute(req, res) {
  doSomethingAsync()
    .then(() => {
      // on resolve / success
      return res.send(200);
    })
    .catch((error) => {
      // on reject / failure
      switch (error instanceof) {
        case NotAllowedError:
          return res.send(400);
        case DatabaseEntryNotFoundError:
          return res.send(404);
        default:
          log('Failed to do something async with an unspecified error: ', error);
          return res.send(500);
      }
    });
}

instanceof は、そのようには動作しません。したがって、後者は失敗します。

Switchステートメントでクラスのインスタンスをチェックする方法はありますか?

43
alextes

適切なオプションは、オブジェクトのconstructorproperty を使用することです。

// on reject / failure
switch (error.constructor) {
    case NotAllowedError:
        return res.send(400);
    case DatabaseEntryNotFoundError:
        return res.send(404);
    default:
        log('Failed to do something async with an unspecified error: ', error);
        return res.send(500);
}

constructorは、オブジェクトが作成されたものと完全に一致する必要があることに注意してください(errorNotAllowedErrorのインスタンスであり、NotAllowedErrorErrorのサブクラスであると仮定します) :

  • error.constructor === NotAllowedErrortrueです
  • error.constructor === Errorfalseです

これにより、スーパークラスにも一致するinstanceofと違いがあります。

  • error instanceof NotAllowedErrortrueです
  • error instanceof Errortrueです

この興味深い投稿constructorプロパティについて確認してください。

77
Dmitri Pavlutin

回避策、if-elseを回避します。見つかった ここ

switch (true) {
    case error instanceof NotAllowedError: 
        return res.send(400);

    case error instanceof DatabaseEntryNotFoundError: 
        return res.send(404);

    default:
        log('Failed to do something async with an unspecified error: ', error);
        return res.send(500);
}
10
ya_dimon

このスイッチケースの代替方法は、エラーのコンストラクターにステータスフィールドを含めることです。

たとえば、次のようにエラーを作成します。

class NotAllowedError extends Error {
    constructor(message, status) {
        super(message);
        this.message = message;
        this.status = 403; // Forbidden error code
    }
}

エラーを次のように処理します。

.catch((error) => {
  res.send(error.status);
});
0
Lachlan Young