【保存版】ESLintの`no-useless-constructor`ルール:知っておけば安心!無駄なコンストラクタの撃退方法と代替手段


ESLint の "no-useless-constructor" ルールは、不要なコンストラクタを検出して警告するものです。

不要なコンストラクタとは、以下のいずれかに該当するコンストラクタを指します。

  • super() 以外の処理しか行っていないコンストラクタ
  • 何もしていないコンストラクタ

これらのコンストラクタは、JavaScript エンジンによって自動的に処理されるため、明示的に定義する必要はありません。

このルールの利点

  • コードレビューで潜在的な問題を発見しやすくなります。
  • 不要なコードを削減することで、メンテナンス性を向上させることができます。
  • コードを簡潔に保つことができます。

このルールの例外

以下の場合は、コンストラクタを定義する必要があります。

  • コンストラクタを使用して、サイドエフェクトを実行する必要がある場合
  • コンストラクタを使用して、他のオブジェクトを初期化する必要がある場合
  • コンストラクタを使用して、インスタンス変数に初期値を設定する必要がある場合

このルールの構成

このルールの動作は、以下のオプションを使用して構成することができます。

  • "allow-empty-constructor": 空のコンストラクタの使用を許可します。デフォルトは false です。
  • "allow-constructor-keyword": constructor キーワードの使用を許可します。デフォルトは false です。

以下のコードは、no-useless-constructor ルールによって警告されます。

class Person {
  constructor() {
    // 何もしません
  }
}

このコードを修正するには、コンストラクタを削除するか、必要な処理を追加します。

class Person {
  constructor(name) {
    this.name = name;
  }
}


不要なコンストラクタの例

何もしていないコンストラクタ

class Person {
  constructor() {
    // 何もしません
  }
}

super() 以外の処理しか行っていないコンストラクタ

class Person extends BasePerson {
  constructor() {
    super();
    console.log('Person クラスが作成されました');
  }
}

コンストラクタキーワードを使用していないコンストラクタ

class Person {
  // コンストラクタ
  name(value) {
    this.name = value;
  }
}

以下のコードは、必要な処理を行っているためno-useless-constructor ルールによって警告されません。

インスタンス変数に初期値を設定するコンストラクタ

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

他のオブジェクトを初期化するコンストラクタ

class Person {
  constructor(address) {
    this.address = new Address(address);
  }
}

サイドエフェクトを実行するコンストラクタ

class Person {
  constructor(name) {
    this.name = name;
    console.log(`新しい人物 ${this.name} が作成されました`);
  }
}

オプションを使用した構成例

以下のコードは、allow-empty-constructor オプションを使用して、空のコンストラクタを許可するように構成しています。

{
  "rules": {
    "no-useless-constructor": ["error", {"allow-empty-constructor": true}]
  }
}

この構成の場合、以下のコードは警告されません。

class Person {
  constructor() {
    // 何もしません
  }
}


ESLint の "no-useless-constructor" ルールは、不要なコンストラクタを検出して警告するものです。しかし、このルールを適用すると、意図した動作と異なる結果になる場合があります。

そこで、ここでは "no-useless-constructor" ルールの代替方法として、以下の 3 つの方法をご紹介します。

コンストラクタロジックを super() に移動する

一部の継承クラスでは、親クラスのコンストラクタで初期化処理を行う必要があり、子クラスのコンストラクタで独自ロジックを追加するケースがあります。

このような場合、no-useless-constructor ルールによって警告が発生してしまう可能性があります。

// 親クラス
class Person {
  constructor(name) {
    this.name = name;
  }
}

// 子クラス
class Student extends Person {
  constructor(name, major) {
    super(name); // 親クラスのコンストラクタ呼び出し
    this.major = major;
  }
}

コンストラクタオプションを使用する

ESLint の "no-useless-constructor" ルールには、以下のオプションが用意されています。

  • "allow-empty-constructor": 空のコンストラクタの使用を許可します。デフォルトは false です。
  • "allow-constructor-keyword": constructor キーワードの使用を許可します。デフォルトは false です。

これらのオプションを使用することで、意図的に不要なコンストラクタを定義している場合でも、警告を抑制することができます。

{
  "rules": {
    "no-useless-constructor": ["error", {"allow-empty-constructor": true}]
  }
}
class Person {
  constructor() {
    // 何もしません
  }
}

カスタム ESLint ルールを作成する

上記の代替方法が適用できない場合は、カスタム ESLint ルールを作成することで、no-useless-constructor ルールの動作を独自に定義することができます。

これは、より複雑なロジックが必要な場合や、特定のケースのみでルールを適用したい場合に有効です。