typescript-eslint/naming-conventionを導入してみた
はじめまして
おはこんばんちは。ラクス フロントエンドチームのさねです。
2022年8月時点で社会人になってから約1年と5ヵ月が経過しました。
エンジニアとして日々開発業務に追われていますが、少しずつ余裕が出てきました。
そこで、次のステップへ進むため私が開発に携わっているプロジェクトの改善作業に挑戦してみました!!
今回の改善作業は「プロジェクトに命名規則を導入させる」です。
命名規則(コーディング規約)とは
まずそもそも命名規則とは?ですが、Wikipediaには
と記載されています。
現在、私が携わっているプロジェクトでは約10名ほどのメンバーが開発をしています。
しかし、命名規則について明示的なルールが定まっていなかったので、命名については各メンバーが他の実装に合わせたり、本などで収集した情報や経験を元に名前をつけていました。
ですので、コードレビューの際に命名について指摘されることもありました。
そんな問題を改善するため今回は、typescript-eslint/naming-conventionを導入してみました。
1.命名規則策定
まずは、命名規則を検討するところから始めました。
今回使用するtypescript-eslint/naming-conventionでは、formatやselectorを指定し、自分でカスタマイズして作成できます。
最初は厳しめに「booleanのメソッドは必ず先頭に"is"を付ける」などの規則を検討してみましたが、「"has"や"exists"を使いたい場面がある」とメンバーからアドバイスをもらったり、厳しめのルールを導入してみた結果、違反数が多すぎて規則を適用しても無意味なことがありました。
そこで色々試行錯誤してみて、下記テーブルのようにselectorとformatの縛りになりました。
テーブル補足
formatでは適用したい名付け規則を指定します。配列なので、複数指定可能です。()が付いているformatは、違反数が多すぎて許容にしたCaseです。将来的には禁止にしたいと考えています。
selectorでは、formatの適用対象を指定します。
規制対象では、selectorの具体的な対象を載せています。表に載っていない規則対象もありますが、プロジェクトで使用していないので省略しています。例:variableにはvarも含まれています。
formatに記載されているCaseについては、以下ルールがあります。
2. 「.eslintrc.js」にルールを追加
命名規則が策定できたらいよいよルールを導入します。
ルールの書き方は、naming-convention.mdを参考にしたら大体書けます。
1点苦戦したのが、特定のファイル(.type.tsまたは.type.js)に例外的なルールを導入したい時に、selectorとmodifiersが被ってしまうと、どちらかだけが適用されてしまう問題が発生しました。
※modifiersは、selectorのより細かい指定ができます。
下記NG例では、namingRulesとtypesNamingRulesのselectorがvaliableで、modifiersがconstになっています。
この場合、大きな括りのselectorは適用されますが、modifierのは適用されません。
NG例
/** 共通の命名規則 */
const namingRules = {
'@typescript-eslint/naming-convention': [
'warn',
// ver,let,constはstrictCamelCaseを使用
{
'selector': 'variable',
'format': ['strictCamelCase']
},
// constはStrictPascalCase,UPPER_CASEを許容
{
'selector': 'variable',
'modifiers': ['const'],
'format': ['strictCamelCase','StrictPascalCase','UPPER_CASE']
},
]
}
/** typeファイルのrules */
const typesNamingRules = {
'@typescript-eslint/naming-convention': [
'warn',
// constはUPPER_CASEを使用
{
'selector': 'variable',
'modifiers': ['const'],
'format': ['UPPER_CASE']
}
]
}
{
// tsファイルrules適用
files: ['**/*.ts'],
rules: namingRules
}
{
// typeファイルrules適用
files: ['**/*.type.ts'],
rules: typesNamingRules
}
解決策としては、下記/** typeファイルのrules */のように、適用したい例外設定を始めに記載し、次に共通のルールを書くことで特定のルールも適用できました。
/**
* 命名規則
*/
const commonWarnNamingRules = [
// var,letはstrictCamelCaseを使用
{
'selector': 'variable',
'format': ['strictCamelCase']
},
// constはstrictCamelCase,StrictPascalCase,UPPER_CASEを使用
{
'selector': 'variable',
'modifiers': ['const'],
'format': ['strictCamelCase','StrictPascalCase','UPPER_CASE']
},
// 関数はstrictCamelCaseを使用、先頭のアンダースコア許容
{
'selector': 'function',
'format': ['strictCamelCase'],
'leadingUnderscore': 'allow'
},
// get,setはstrictCamelCaseを使用
{
'selector': 'accessor',
'format': ['strictCamelCase']
},
// 関数パラメーターはstrictCamelCaseを使用、先頭のアンダースコア許容
{
'selector': 'parameter',
'format': ['strictCamelCase'],
'leadingUnderscore': 'allow'
},
// typeはStrictPascalCase,UPPER_CASEを使用
{
'selector': 'typeAlias',
'format': ['StrictPascalCase', 'UPPER_CASE']
},
// classはStrictPascalCaseを使用
{
'selector': 'class',
'format': ['StrictPascalCase']
},
// interfaceはStrictPascalCaseを使用
{
'selector': 'interface',
'format': ['StrictPascalCase']
}
]
/** 共通命名rules */
const namingRules = {
'@typescript-eslint/naming-convention': [
'warn',
...commonWarnNamingRules
]
}
/** typeファイルのrules */
const typesNamingRules = {
'@typescript-eslint/naming-convention': [
'warn',
// constはUPPER_CASEを使用
{
'selector': 'variable',
'modifiers': ['const'],
'format': ['UPPER_CASE']
},
...commonWarnNamingRules
]
}
{
// tsファイルrules適用
files: ['**/*.ts'],
rules: namingRules
}
{
// typeファイルrules適用
files: ['**/*.type.ts'],
rules: typesNamingRules
}
あとは上記ruleを読み込むようにして命名規則の導入は完了しました!
導入後の結果は下記のようになります。
ちゃんと、constはUPPER_CASEを使うように警告が出ています。
定数名をUPPER_CASEに修正すると、警告がなくなりました!
命名規則について、どのCaseを使うか教えてくれるのは便利です。
以上が改善作業になります。
最後に
今回、命名規則の導入を行ってみて、設定系のファイルを編集することが無かったので良い経験になりました。
また、現在の運用方針を見直すきっかけになれたと思います。
今回は基本的な命名規則しか作れなかったので、将来的には特定の単語を禁止にしたり、ルールを作らなくても命名規則が合うようにしていきたいです。
おまけ
今回naming-conventionを導入した際に、どれくらい警告数が出ているか気になったので、eslint-nibbleで計測を行いました。
eslint-nibbleでは、導入したルールの警告数や違反数が、どのファイルで出ているのか特定できるので、非常におススメです!!