ちょっと話題の記事

ESLintでTypeScriptの変数の名付け規則をチェックしよう!

2020.07.27

はじめに

@typescript-eslintの3系では、@typescript-eslint/camelcaseが廃止され、代わりに@typescript-eslint/naming-convention利用が推奨されています。(詳しい内容は、こちらの項Rule Removals)

@typescript-eslint/naming-conventionは、名付け規則を柔軟に定義することが可能です。 定義することで、eslintの設定ファイルがそのままそのままコーディング規約となります。

本記事では、@typescript-eslint/naming-conventionの設定方法について書きます。

基本的にtypescript-eslintのnaming-convention.mdの内容を参考にしており、本記事で疑問を感じた場合参照することをお勧めします。

ルールの導入方法

.eslintrc.jsonに下記を追記します

"rules": {
  "@typescript-eslint/naming-convention": [
    "error",
    {
      "selector": "class",
      "format": ["PascalCase"],
      "custom": {
        "regex": "send|start|find",
        "match": false
      }
    }
  ]
}

各設定について見ていきます

適用したい名付け規則の指定

formatには、適用したいformatを指定します。配列なので、複数指定可能です。 指定できるformatは下記の表の通りです。

format 説明 NG例
camelCase 文字間のアンダースコアは許可されず、連続した大文字は許可 myId, myID
strictCamelCase camelCaseと同じ、ただし連続した大文字は非許可 myId myID
PascalCase camelCaseと同じ、ただし最初の文字は大文字 MyId, MyID
StrictPascalCase strictCamelCaseと同じ、ただし最初の文字は大文字 MyId MyID
snake_case 全て小文字で、アンダースコアが利用可能 my_id
UPPER_CASE 全て大文字で、アンダースコアが利用可能 MY_ID

名付け規則を適用する対象を指定する

selectorには、formatで指定した名付け規則を適用する対象を指定します。

例えばselectorvariablesを指定すると、var,let,constで定義した変数に対して、formatで指定した規則が適用されます。

selector 名付け規則を適用する対象
variable var,let,const
function
parameter 関数パラメータ
property オブジェクト,クラス,オブジェクトタイプのメソッド
parameterProperty 任意のパラメータプロパティ
method オブジェクト,クラス,オブジェクトタイプのメソッド
accessor アクセッサ
enumMember enumのメンバ
class
interface
typeAlias type
enum
typeParameter ジェネリック型パラメーター(型引数)

上記をグループ化したGroup Selectorsも定義されています。詳しくはこちら

関数の引数にcamelCaseを強制する

.eslintrc.jsonの設定は、下記の通り

{
  "@typescript-eslint/naming-convention": [
    "error",
    {
      "selector": "parameter",
      "format": ["camelCase"]
    },
  ]
}

下記の画像の通り、エラーが検出されています。エラーの内容から、camelCaseする必要があることが分かるので、そのまま修正可能です。

具体例を見ていく

上記はシンプルな例でしたが、他にもより柔軟な名付け規則を適用可能です。

これから説明する例は、typescript-eslint/typescript-eslintのExamplesを参考にしています。

boolean型の変数名に特定のprefixを強制する

下記のような設定をします。

  • let, const, varで宣言した変数がboolean型の場合、prefixにisもしくはshouldを強制
  • let, const, varで宣言した変数がboolean型でない場合、名付け規則は自由

.eslintrc.jsonの設定は、下記の通り

{
  "@typescript-eslint/naming-convention": [
    "error",
    {
      "selector": "variable",
      "types": ["boolean"],
      "format": ["PascalCase"],
      "prefix": ["is", "should"]
    }
  ]
}

設定をみておや?と思った方いると思います。formatPascalCaseが指定されている点です。 これは本ルールの名付け規則の検証ロジックの影響です。詳しく見ていきます。

下記の順で名付け規則がチェックされます。isEnableという変数を検証した際の例は、()に記述しています。

  1. 主要なアンダースコアを検証する(アンダースコアルールはないので検証OK)
  2. 末尾のアンダースコアを検証する(同上)
  3. プレフィックスを検証(isEnableのisをチェックし存在するので検証OK。isがトリミングされてEnableとなる)
  4. サフィックスを検証する(Enable)
  5. カスタムを検証する(Enable)
  6. 名付け規則を検証する(EnableがPascalCaseでtrueなので検証OK)

上記より、下記のコードの場合enableisenableがエラーとして検出されます。

const isEnable = false;
// エラーなし
// 前述の通り、isがトリミングされEnableがPascalCaseなのでOK

const enable = false;
// エラー内容から分かる通り、前述項3の検証で失敗し、エラー
// [エラー内容]17:9  error  Variable name `enable` must have one of the following prefixes: is, should, has, can, did, will  @typescript-eslint/naming-convention

const isenable = false;
// エラー内容から分かる通り、前述項6の検証で失敗し、エラー
// [エラー内容]18:9  error    Variable name `isenable` trimmed as `enable` must match one of the following formats: PascalCase  @typescript-eslint/naming-convention

const hoge = 'test';
// エラーなし
// booleanではないためprefixもPascalCaseであることも強制されない

インターフェースがIで始まっていないことを強制する

.eslintrc.jsonの設定は、下記の通り

{
  "@typescript-eslint/naming-convention": [
    "error",
    {
      "selector": "interface",
      "format": ["PascalCase"],
      "custom": {
        "regex": "^I[A-Z]",
        "match": false
      }
    }
  ]
}

customオプションは、名付け規則が正規表現に一致するもしくは一致しないことを強制することが出来ます。 matchオプションがtrueの場合はregexオプションが一致することを強制します。

本例では、falseになっていますのでregexオプションの正規表現に一致しないことを強制します。下記のコードだと、コメント部のようなエラーが出力されます。

interface IPerson {
  age: number;
  name: string;
}
// [エラー内容]15:11  error    Interface name `IPerson` must not match the RegExp: /^I[A-Z]/u                                    @typescript-eslint/naming-convention

最後に

@typescript-eslint/naming-conventionの設定方法について解説しました。とても細かく変数の名付け規則を検証できるので、@typescript-eslintの3系にアップデートする際に一度見直すと良いかもしれません。