ESLintでTypeScriptのコーディング規約チェックを自動化しよう
本章では、ESLintを使って、TypeScriptをチェックするためのノウハウをチュートリアル形式で学びます。
本章で学べること
本章では次のことを学んでいただきます。
- コーディング規約の必要性とコーディング規約の問題点
- ESLintでJavaScriptやTypeScriptをチェックする方法
- ESLintのルールの設定のしかた
- Airbnbのコーディング規約をESLintで活用する術
- エラーを解消する方法
- チェックを部分的に無効化する方法
- VS CodeやJetBrains IDEとESLintを統合する方法
チュートリアルをやり終えると、ご自身のプロジェクトにESLintを導入できるようになったりと、実務で役立つ基本的なスキルが身につくはずです。
本章の流れと読み進め方
本章は次の3部構成です。
本章の前半は座学です。「コーディング規約」や「リンター」が何か知らない方向けに、その背景知識を解説します(背景知識)。すでにコーディング規約やリンターが分かっている方、すぐに手を動かしたい方は、ここは読み飛ばしても構いません。
本章の後半はチュートリアルです。本章のゴールは、TypeScriptをESLintでチェックできるようになることです。しかしながら、ESLintでTypeScriptを扱うのは発展的な用法です。そこで、チュートリアルの流れとしては、まず基礎編として、JavaScriptをESLintで扱う方法を学びます(ESLintでJavaScriptをリントしよう)。その後、TypeScriptをESLintを扱う方法を学んでいただきます(ESLintでTypeScriptをリントしよう)。
章末にはおまけとして次のチュートリアルも用意してあります。関心と余力がある方はこちらもご覧ください。
このチュートリアルに必要なもの
このチュートリアルで必要なものは次のとおりです。
- Node.js v16以上
- NPM v7系以上
- Yarn v1系 (このチュートリアルはv1.22.18で動作確認しています)
Node.jsの導入については、開発環境の準備をご覧ください。
パッケージ管理ツールとしてYarnを利用します。最初にインストールをしておきましょう。すでにインストール済みの方はここのステップはスキップして大丈夫です。
shellnpm install -g yarn
shellnpm install -g yarn
背景知識
TypeScriptの書き方はさまざま
TypeScriptに限らず、プログラミング言語には文法があります。文法を守って書かれたコードは、エラーなく実行やコンパイルができます。
プログラムは文法さえ守れば、誰が書いても一字一句同じコードになるかというと、そうではありません。たとえば、TypeScriptでは文末のセミコロンが省略できます。次の2行のコードの違いは、セミコロンの有無です。どちらも文法的に正しく、どちらを使うかは好みの問題です。
tsconsole .log ("OK")console .log ("OK");
tsconsole .log ("OK")console .log ("OK");
文字列はシングルクォート、ダブルクォート、バッククォートの3通りで書けます。シングルクォートとダブルクォートは機能上の違いがありません。バッククォートはテンプレートリテラルと言い、文字列リテラルとは仕様が異なります。しかし、次の例のような単純な文字列では、この3つは同じ意味になります。
tsconsole .log ('OK');console .log ("OK");console .log (`OK`);
tsconsole .log ('OK');console .log ("OK");console .log (`OK`);
この例は、どれを使うか意見が割れるところです。本書独自の調査では、「原則的にどれをもっとも多く使うか?」という問いに対し、シングルクォートが55%ともっとも多く、次にダブルクォートが29%、バッククォートは16%という回答が得られました。(回答数232件)
上でとりあげた例はほんの一例です。意味が同じで書き方が異なる例は、数多くあります。
書き方の違いが問題になることも
書き方の違いが問題なることがあります。たとえば、プログラムを共同で開発する場合です。人によって書き方が異なると、その違いが気になったり驚いたりして、コードの本筋が頭に入ってこないことがあります。インデントの幅が統一されていないと、コードが読みにくくなることもあります。結果的に、書き方に違いがあるとプログラムの保守性を損ねる一因になります。
コーディング規約で書き方を統一
理想は、誰が書いても同じコードになることです。そのためにはどうしたらよいでしょうか。解決策のひとつは、書き方のルールを決めることです。コードの書き方の取り決めは「コーディング規約(coding standards)」と呼ばれます。
コーディング規約では、たとえば、次のようなことを決めます。
- 変数名はキャメルケースにしましょう。
functionの中カッコは関数名と同じ行に書きましょう。(次の行に置いてはなりません)console.logは消しましょう。- if文の条件式で変数代入してはいけません。たとえば
if (data = getData())はだめ。
このようなルールを取りまとめて規約を作るのですが、実用的な規約に仕上げるにはかなりの労力を要します。実務では、公開されている規約を借りてくるほうが現実的です。
公開されている規約には主に次のものがあります。これらは実際に多くのプロジェクトで利用されています。
コーディング規約をチームのみんなで守れば、書き方を統一しやすくなります。
コーディング規約の問題点
コーディング規約にも問題点があります。
運用の手間は少なくない
開発者ひとりひとりが規約を守れば、コーディング規約は機能します。しかし、ヒューマンエラーは起きるものです。規約を知った上で破る場合もありますが、多いのは知らずに破ってしまうことや、間違えてしまうことです。もしも、規約が守られなければ、規約は形式上のものになってしまいます。そうなると、書き方を統一するという目標は達成できなくなってしまいます。
ヒューマンエラーを防ぐには、コードが規約に準拠しているかを日々点検しなければなりません。しかし、これには多くの労力がかかります。もっと重要な仕事がある中で、点検を行うのは無理な場合もあるかもしれません。規約を正しく運用するには、多くの手間がかかるのです。
コミュニケーション上の心理的な負担が増す
コーディング規約は、何が正しく、何が間違いかを定めます。すると、明らかに誤りと判断できるコードが出てきます。他者が書いたコードの誤りを指摘する場面も出てきます。人の仕事の誤りを指摘するのは難しいものです。想像以上に心理的な負担になります。指摘する側は相手の心象を悪くしないよう、伝え方に苦慮します。指摘される側も、前向きに受け取れない場合もあります。相手との対人関係によっては、指摘することが遠慮される場合もあります。
コーディング規約の自動化
書き方を統一するには、コーディング規約は不可欠です。しかし、運用の手間や心理的な課題もあります。これを解決する手助けとなるのがESLintです。ESLintは、JavaScriptやTypeScriptのコードがコーディング規約に準拠しているかをチェックするツールです。
ESLintは、コマンドひとつでチェックが行なえます。チェックは数秒で完了し、すぐに結果がわかります。そのため、点検の手間がほぼなくなります。
加えて、自動修正機能もあります。コードによっては、ESLintが規約に準じたコードに直せる場合もあります。この機能を利用できる場合は、規約違反箇所を修正する手間もなくせます。
不思議なもので、同じ指摘でも人に言われるより、機械に指摘されたほうが気が楽なものです。ESLintでは機械的に問題を指摘してくれるため、コミュニケーション上の心理的負担も軽減できます。
ESLintを導入すると、開発者は規約の運用や心理的ストレスから開放され、開発などのより重要な仕事に集中できるようになります。
学びをシェアする
📝TypeScriptは同じ意味処理でも異なる書き方が可能
💥チーム開発では書き方の違いが問題になることも…
🤝書き方統一のためにコーディング規約を導入しよう
😵でも、規約には運用の手間や心理的な課題もある
✅この課題はESLintで解決できる!
『サバイバルTypeScript』より
リンターとは
ESLintは一般的に「リンター(linter)」というジャンルのツールです。リンターは、プログラムを静的に解析し、バグや問題点を発見するツールを言います。リンターを使って、問題点を解析することを「リントする(lint)」と言います。
リント(lint)の由来は紡績です。羊毛や綿花から、繊維をつむぐ際に不要になるホコリのような糸くずをリントと呼びます。紡績ではリントを取り除く工程があり、これにちなんでプログラミングでもリントという名前が使われだしたと言われています。
コンパイラとリンターの違い
コンパイラの本質は、ある言語から別の言語に変換することです。TypeScriptコンパイラの場合は、TypeScriptからJavaScriptへの変換です。
リンターの本質は、プログラムの問題点を指摘することです。言語から言語への変換は行いません。
実際は、TypeScriptコンパイラもプログラムの問題点を報告します。たとえば、コンパイラオプションnoUnusedLocalsを有効にすると、未使用の変数をチェックできます。ESLintにもこれと同等のチェックがあります。こうした点はリンターの機能と重複する部分です。
類似のチェック機能があるものの、両者は得意分野が異なります。TypeScriptコンパイラは型のチェックが充実しています。型の側面から問題点を発見するのが得意です。一方、ESLintはインデントや命名規則などのコーディングスタイルや、どのようなコードを書くべきか避けるべきかの意思決定、セキュリティやパフォーマンスに関する分野でのチェックが充実しています。どちらも相互補完的な関係です。したがって、コンパイラとリンターの両方を導入すると、より幅広いチェックが行えるようになります。
| TypeScriptコンパイラ | ESLint | |
|---|---|---|
| 言語から言語への変換 | ○ | |
| 型のチェック | ○ | |
| 構文チェック | ○ | ○ |
| コーディングスタイル | ○ | |
| コードの意思決定 | ○ | |
| セキュリティ | ○ | |
| パフォーマンス | ○ |
学びをシェアする
🧵リンター:コードを静的解析し問題点を指摘するツール。ESLintはリンター。
🔀コンパイラ:静的解析もするが、別言語への変換が主目的。tscはコンパイラ。
⚖️tscとESLintの相違点
・tsc:型のチェックが得意
・ESLint:コーディング規約のチェックが得意
『サバイバルTypeScript』より
ESLintでJavaScriptをリントしよう
ここからはESLintの導入方法や使い方をチュートリアル形式で説明していきます。ぜひお手元の環境で実際にトライしてみてください。
プロジェクトを作成する
まず、このチュートリアルに使うプロジェクトを作成します。
shellmkdir eslint-tutorialcd eslint-tutorial
shellmkdir eslint-tutorialcd eslint-tutorial
プロジェクトルートにpackage.jsonを作ってください。その内容は次のようにします。
package.jsonjson{"name": "eslint-tutorial","license": "UNLICENSED"}
package.jsonjson{"name": "eslint-tutorial","license": "UNLICENSED"}
ESLintを導入する
ESLintはYarnでインストールしましょう。ESLintは開発時だけ使うパッケージなので、yarn addコマンドには-Dオプションをつけてインストールします。
shellyarn add -D 'eslint@^8'
shellyarn add -D 'eslint@^8'
Next.jsは最初からESLintが導入されています。実務でNext.jsプロジェクトでESLintを使う場合は、導入ステップは省略できます。
ESLintが正しくインストールされたか、バージョンを表示して確認してください。
shellnpx eslint -vv8.15.0
shellnpx eslint -vv8.15.0
ちなみにこのnpxコマンドは、Nodeモジュール(ライブラリ)の実行ファイルを起動するツールです。npx eslintを実行すると、./node_modules/.bin/eslintが実行されます。
ESLintの設定ファイルを作る
ESLintの設定ファイル.eslintrc.jsをプロジェクトルートに作ってください。
shelltouch .eslintrc.js
shelltouch .eslintrc.js
設定ファイル作成後のディレクトリ構造text.├── .eslintrc.js├── node_modules├── package.json└── yarn.lock
設定ファイル作成後のディレクトリ構造text.├── .eslintrc.js├── node_modules├── package.json└── yarn.lock
設定ファイルの内容は次のようにします。
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},};
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},};
この設定内容は次で説明します。
root
eslintコマンドを実行したディレクトリを起点に、ディレクトリをさかのぼって設定ファイルを探す仕様がESLintにはあります。たとえば、ディレクトリ/a/b/でコマンドを実行した場合、ESLintは次の順で設定ファイルを探します。
/a/b/.eslintrc.js/a/.eslintrc.js/.eslintrc.js
この探索はルートディレクトリに達するまでさかのぼります。探索中に複数の設定ファイルが見つかった場合は、設定内容がマージされていきます。この仕様は便利な反面、プロジェクト外の設定ファイルまで見にいってしまう危険性もあります。設定ファイルの探索範囲をしぼるためにも、rootにtrueを設定するのがお勧めです。これがある設定ファイルが見つかると、これ以上ディレクトリをさかのぼらなくなります。
env
envはチェック対象のJavaScript/TypeScriptコードがどの実行環境で使われるかをESLintに伝えるためのオプションです。これを設定すると、ESLintがグローバル変数を認識するようになります。たとえば、browser: trueを設定すると、windowやalertなどのグローバル変数が認識されます。es2021を設定すると、ES2021までに導入されたグローバル変数が認識されます。他にもnodeなどの指定ができます。指定できる実行環境の一覧は公式ドキュメントをご覧ください。
この設定は、ESLintのno-undefルールに関係します。このルールは未定義の変数をチェックするルールです。グローバル変数は定義せずに利用できる変数です。ESLintはどのグローバル変数が定義済みかを知らないと、このルールを正しく適用できません。そのため、envオプションは正しく設定する必要があります。
parserOptions
ecmaVersion
parserOptionsはチェック対象のJavaScriptがどの構文を使っているかをESLintに伝えるためのオプションです。ecmaVersionは、どのバージョンのECMAScriptの構文を使うかを指定します。"latest"を設定すると、最新のECMAScriptの構文を使うという指定になります。デフォルトではECMAScript 5になっています。これはかなり古いバージョンです。実務ではES5で開発することはまれなので、ここは必ず指定しましょう。なお、envオプションでes2022などECMAScriptのバージョンを指定している場合、ecmaVersionにも自動的にes2022が設定されます。どちらも同じバージョンを指定する場合は、ecmaVersionの指定は省略できます。
sourceType
JavaScriptにはスクリプトモードとモジュールモードがあります。sourceTypeはJavaScriptコードがどちらのモードで書かれるかを指定するオプションです。モジュールモードでは、import文やexport文といった追加の構文がサポートされます。sourceTypeのデフォルト値は"script"(スクリプトモード)です。実務で開発する場合は、モジュールモードでJavaScript/TypeScriptを書くほうが普通なので、sourceTypeには"module"(モジュールモード)を指定しましょう。
ESLintのルールを設定する
ESLintには「ルール(rule)」という概念があります。ルールはチェックの最小単位です。たとえば、ルールには次のようなものがあります。
no-console:console.logを書いてはならないcamelcase: 変数名はキャメルケースにすることsemi: 文末セミコロンは省略しない
ESLintには200を超えるルールがあります。全ルールのリストは公式ドキュメントにあります。
ESLintでは、複数のルールを組み合わせてコーディング規約を組み立てていきます。
ルールには、重大度(severity)という重み付けが設定できます。重大度は、off、warnとerrorの3種類です。offはルールを無効化し、チェックを行わなくする設定です。warnは発見した問題を警告として報告します。報告はするものの、eslintコマンドの終了コードには影響しません。errorは発見した問題をエラーとして報告し、終了コードを1にする効果があります。それぞれの重大度は、0から2までの数値で設定することもできます。
| 重大度 | 数値 | 効果 |
|---|---|---|
| off | 0 | ルールをオフにする |
| warn | 1 | 警告するが終了コードに影響しない |
| error | 2 | 警告し、終了コードを1にする |
ルールは.eslintrc.jsのrulesフィールドに、ルール名: 重大度のキーバリュー形式で書きます。まずは、no-consoleをルールに追加してみましょう。
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},rules : {"no-console": "error",},};
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},rules : {"no-console": "error",},};
ルールによっては、細かく設定できるものもあります。たとえば、camelcaseです。これは変数名がキャメルケースかをチェックするルールです。変数の種類によっては、キャメルケース以外が使いたい場合があります。たとえば、プロパティ名はアンダースコアを使いたいことがあるかもしれません。ウェブAPIによっては、JSONオブジェクトがスネークケース(foo_barのようなアンダースコア区切り)を採用している場合があるからです。この場合、ルール名: [重大度, 設定値]のような配列形式で設定することで、細かいルール設定ができます。次の設定例は、プロパティ名に限ってはキャメルケースを強制しない設定です。試しに、この設定を.eslintrc.jsに加えてみましょう。
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},rules : {"no-console": "error",camelcase : ["error", {properties : "never" }],},};
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},rules : {"no-console": "error",camelcase : ["error", {properties : "never" }],},};
- package.jsonを作りました。
- eslintをインストールしました。
- 設定ファイル
.eslintrc.jsを作りました。 - 設定ファイルには次のルールを追加しました。
no-console:console.logをコードに残しておいてはいけない。camelcase: 変数名はキャメルケースにすること(プロパティ名を除く)。
JavaScriptをチェックする
設定ファイルが準備できたので、JavaScriptファイルを作り、ESLintでチェックしてみましょう。
まず、srcディレクトリを作ってください。
shellmkdir src
shellmkdir src
srcディレクトリにJavaScriptファイルhelloWorld.jsを作ってください。
shelltouch src/helloWorld.js
shelltouch src/helloWorld.js
helloWorld.jsが加わったディレクトリ構造が、次のようになっているか確認してください。
txt.├── .eslintrc.js├── node_modules├── package.json├── src│ └── helloWorld.js└── yarn.lock
txt.├── .eslintrc.js├── node_modules├── package.json├── src│ └── helloWorld.js└── yarn.lock
helloWorld.jsの内容は次のようにします。
src/helloWorld.jsjsexport consthello_world = "Hello World";console .log (hello_world );
src/helloWorld.jsjsexport consthello_world = "Hello World";console .log (hello_world );
このhelloWorld.jsは、わざとコーディング規約に違反するコードになっています。1行目の変数hello_worldはキャメルケースになっていません。2行目では、使ってはいけないconsole.logが使われています。
では、ESLintでチェックを実行してみましょう。チェックは、eslintコマンドを起動するだけです。eslintコマンドは第一引数に、チェック対象のファイル名やディレクトリ名を指定します。ここでは、srcディレクトリ全体をチェックするために、引数はsrcにします。
srcディレクトリをESLintでチェックするshellnpx eslint src
srcディレクトリをESLintでチェックするshellnpx eslint src
これを実行すると、次の出力が表示されます。
結果の読み方
チェックした結果、問題点が見つかると表形式で詳細が表示されます。各行は4つの列からなります。左から順に、コードの行番号列番号、重大度、問題点の説明、ルール名です。
結果に表示されている内容だけでは、どうして問題点になっているのか、どう直したらいいのかが分からないことがあります。その場合は、ルール名からESLintのドキュメントでルールの詳細を調べます。たとえば、上の結果ではルール名にno-consoleが挙がっていますが、この文字列をもとにルールの詳細を探します。no-consoleの詳細ページは、https://eslint.org/docs/rules/no-consoleにあります。
コードを修正してエラーを解消する
src/helloWorld.jsjsexport consthello_world = "Hello World";console .log (hello_world );
src/helloWorld.jsjsexport consthello_world = "Hello World";console .log (hello_world );
上のコードをESLintでチェックした結果、2つの問題点が指摘されました。
- 1行目: 変数名
hello_worldがキャメルケースではない - 2行目:
console.logは使ってはいけない
このエラーを解消したいので、helloWorld.jsを編集してみましょう。変数名hello_worldはhelloWorldに変更します。2行目のconsole.logは削除しましょう。修正後のコードは次のようになります。
src/helloWorld.jsjsexport consthelloWorld = "Hello World";
src/helloWorld.jsjsexport consthelloWorld = "Hello World";
再びESLintでチェックして、もう問題がなくなっているか確認してみましょう。
shellnpx eslint src
shellnpx eslint src
この実行結果に何も出力されなければ、問題点が解消されています。
コードを自動修正する
ESLintのルールの中には、コードの自動修正ができるものがあります。たとえば、semiは、文末セミコロンをつけるつけないを定めるルールですが、これは自動修正に対応しています。ここでは、semiを使ってESLintの自動修正をためしてみましょう。
まず、設定ファイル.eslintrc.jsのrulesにsemiを追加します。
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},rules : {"no-console": "error",camelcase : ["error", {properties : "never" }],semi : ["error", "always"],},};
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},rules : {"no-console": "error",camelcase : ["error", {properties : "never" }],semi : ["error", "always"],},};
このルール設定では、"always"を指定しています。これは、文末セミコロンを必須にする設定です。
つぎに、src/helloWorld.jsのコードのセミコロンを消して保存してください。
src/helloWorld.jsjsexport consthelloWorld = "Hello World"
src/helloWorld.jsjsexport consthelloWorld = "Hello World"
自動修正の前にチェックだけを実行し、semiについての問題が報告されるか確認します。
shellnpx eslint src
shellnpx eslint src
次のような結果が表示されれば、追加したsemiルールが効いていることになります。
ESLintでコードを自動修正するには、eslintコマンドに--fixオプションをつけます。次のコマンドを実行し、自動修正してみましょう。
shellnpx eslint src --fix
shellnpx eslint src --fix
自動修正が成功していれば、出力は何も表示されずに処理が終了します。自動修正が効いているかを確認するために、src/helloWorld.jsを開いてみてください。文末にセミコロンが追加されているでしょうか。追加されていれば自動修正成功です。
src/helloWorld.jsを作りました。npx eslint srcを実行し、srcディレクトリをチェックしてみました。- コードを手直しして、ESLintのチェックを通過する流れを体験しました。(
camelcase,no-console) npx eslint src --fixを実行し、ESLintの自動修正機能を試しました。(semi)
ESLintにはどんなルールがある?
ここまでのチュートリアルでは3つのルールを扱いました(camelcase、no-console、semi)。ESLintにはもっと多くのルールがあります。ルール数は200を超えます。
ルールの一覧は、公式ドキュメントのRulesにあります。この一覧では、どのルールが自動修正に対応しているかも確認できます。
Shareable configを導入する
ESLintのルールは数があまりにも多いため、ルールをひとつひとつ調べて導入していくのは大変です。そこで、お勧めなのがshareable configの活用です。
shareable configは、誰かが設定したルールのプリセットです。これを導入すると、自分でルールを設定する手間が省けます。
有名なshareable configのひとつに、ESLint公式が公開しているeslint:recommendedがあります。これを導入すると、Rulesの一覧でチェックマークがついているルールが一括して有効化されます。これは公式が提供してるため有名ですが、有効になっているルールが少ないため、実務では物足りなさがあるかもしれません。
第三者が公開しているshareable configもあり、次にあげるものは実務でも広く使われています。
上のshareable configはコーディング規約に基づいて作成されているため、文書としてのコーディング規約とESLintの設定をセットでプロジェクトに導入できる利点があります。
このチュートリアルでは、人気のAirbnbのものを使っていきます。Airbnbの設定には、eslint-config-airbnbとeslint-config-airbnb-baseの2つがあります。前者は、React向けの設定が追加で盛り込まれています。今回はReactは扱わないので、よりシンプルな後者を導入します。
まず、Yarnでeslint-config-airbnb-baseをインストールします。その際、合わせてeslint-plugin-importも導入します。
shellyarn add -D \'eslint-config-airbnb-base@^15' \'eslint-plugin-import@^2'
shellyarn add -D \'eslint-config-airbnb-base@^15' \'eslint-plugin-import@^2'
次に、設定ファイル.eslintrc.jsのrulesを消します。その上で、extends: ["airbnb-base"]を追加してください。
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},extends : ["airbnb-base"],};
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},extends : ["airbnb-base"],};
これで、shareable configの導入は完了です。
チェックを試すために、src/helloWorld.jsを次の内容に置き換えてください。
src/helloWorld.jsjsexport consthello_world = "Hello World";console .log (hello_world );
src/helloWorld.jsjsexport consthello_world = "Hello World";console .log (hello_world );
このコードはAirbnbの規約にわざと違反する内容になっています。
最後にeslintを実行し、チェックを動かしてみましょう。
shellnpx eslint src
shellnpx eslint src
すると、次のような結果が得られるはずです。
ここで報告されている問題点は、次のような内容になります。
import/prefer-default-export: デフォルトエクスポートを使わければなりません。camelcase: 変数hello_worldはキャメルケースでなければなりません。quotes: 文字列リテラルはシングルクォートで囲む必要があります。no-console:console.logは残しておいてはいけません。
続いて、shareable configのルールを上書きする方法を学んでいきましょう。
上の結果では、import/prefer-default-export違反が報告されていました。これは、名前付きエクスポート(export const helloWorld = "...")ではなく、デフォルトエクスポート(export default "...")にすべきというエラーです。しかし、ここでは名前付きエクスポートを使いたいので、このルールをオフにすることで警告されないようにしてみましょう。ルールを上書きするには、.eslintrc.jsのrulesに"import/prefer-default-export": "off"を追加します。
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},extends : ["airbnb-base"],rules : {"import/prefer-default-export": "off",},};
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},extends : ["airbnb-base"],rules : {"import/prefer-default-export": "off",},};
さらに、文字列リテラルはダブルクォートのほうを使いたいので、rulesにquotes: ["error", "double"]を追加します。
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},extends : ["airbnb-base"],rules : {"import/prefer-default-export": "off",quotes : ["error", "double"],},};
.eslintrc.jsjsmodule .exports = {root : true,env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",},extends : ["airbnb-base"],rules : {"import/prefer-default-export": "off",quotes : ["error", "double"],},};
再びeslintを実行して、ルールの上書きが効いているか確認してみましょう。
shellnpx eslint src
shellnpx eslint src
次のように、出力結果からデフォルトエクスポートと文字列クォートについての警告が消えていれば、ルールが効いています。
ルールを部分的に無効化する
.eslintrc.jsで設定した規約はプロジェクト全体に及びます。コードを書いていると、どうしても規約を破らざるをえない部分が出てくることがあります。その場合は、コードのいち部分について、ルールを無効化することもできます。
部分的にルールを無効にするには、その行の前にコメントeslint-disable-next-lineを追加します。たとえば、次の例ように書いておくと、変数名hello_worldがキャメルケースでなくても、ESLintは警告を出さなくできます。
js// eslint-disable-next-line camelcaseexport consthello_world = "Hello World";
js// eslint-disable-next-line camelcaseexport consthello_world = "Hello World";
この方法はいざというときに知っておくとよいというものです。ルール無効化コメントだらけになってしまうと本末転倒です。節度を持って使うのが望ましいです。
- shareable configの
eslint-config-airbnb-baseを導入しました。 - これのルールを一部上書きしてみました。
import/prefer-default-exportを無効化quotesの指定をシングルクォートからダブルクォートに変更
- ルール無効化コメント
// eslint-disable-next-lineを試しました。
ESLintでTypeScriptをリントしよう
ここまでのチュートリアルでは、JavaScriptにESLintをかける方法を学んできました。ここからは、TypeScriptにESLintを使う方法を学んでいきます。
そもそもESLintでは、TypeScriptはチェックできません。これを補うのがTypeScript ESLintです。これを導入するとESLintでTypeScriptがチェックできるようになります。
プロジェクトを作成する
ここからは別のプロジェクトを作り、その新プロジェクトでチュートリアルを進めていきます。空のディレクトリを作り、その中に最低限のpackage.jsonを配置してください。
shellmkdir eslint-typescript-tutorialcd eslint-typescript-tutorial/echo '{"name": "eslint-typescript-tutorial","license": "UNLICENSED"}' > package.json
shellmkdir eslint-typescript-tutorialcd eslint-typescript-tutorial/echo '{"name": "eslint-typescript-tutorial","license": "UNLICENSED"}' > package.json
TypeScriptを導入する
TypeScript ESLintを使うには、TypeScript環境を構築しておく必要があります。まず、typescriptを導入しておいてください。合わせてNode.jsの型定義@types/nodeもインストールしておきます。この型情報は、.eslintrc.jsなどのNode.js環境で実行されるファイルをESLintでチェックするときに利用されます。
shellyarn add -D 'typescript@^4.6' '@types/node@^16'
shellyarn add -D 'typescript@^4.6' '@types/node@^16'
TypeScriptコンパイラの設定ファイルも作っておきます。
shelltouch tsconfig.json
shelltouch tsconfig.json
tsconfig.jsonの内容はこうします。
tsconfig.jsonjson{"compilerOptions": {"outDir": "dist"},"include": ["src"]}
tsconfig.jsonjson{"compilerOptions": {"outDir": "dist"},"include": ["src"]}
続いて、srcディレクトリにTypeScriptファイルhelloWorld.tsを追加します。内容は空で構いません。
shellmkdir srctouch src/helloWorld.ts
shellmkdir srctouch src/helloWorld.ts
コンパイルもできるか試してみましょう。
shellnpx tsc
shellnpx tsc
コンパイルが成功すると、dist/helloWorld.jsが生成されます。
この段階では、ディレクトリ構成が次のようになっているはずです。
ディレクトリ構成text.├── dist│ └── helloWorld.js├── node_modules├── package.json├── src│ └── helloWorld.ts├── tsconfig.json└── yarn.lock
ディレクトリ構成text.├── dist│ └── helloWorld.js├── node_modules├── package.json├── src│ └── helloWorld.ts├── tsconfig.json└── yarn.lock
TypeScript ESLintを導入する
ESLint本体とTypeScript ESLintの両方をインストールします。
shellyarn add -D \'eslint@^8' \'@typescript-eslint/parser@^5' \'@typescript-eslint/eslint-plugin@^5'
shellyarn add -D \'eslint@^8' \'@typescript-eslint/parser@^5' \'@typescript-eslint/eslint-plugin@^5'
TypeScript ESLintは2つのパッケージから成ります。@typescript-eslint/parserは、ESLintにTypeScriptの構文を理解させるためのパッケージです。@typescript-eslint/eslint-pluginは、TypeScript向けのルールを追加するパッケージです。
ESLintがインストールされ、実行可能になっているかバージョンを表示して確認しましょう。
shellnpx eslint -vv8.15.0
shellnpx eslint -vv8.15.0
TypeScript ESLintにはどんなルールがある?
ESLintの200以上のルールに加えて、TypeScript ESLintを導入すると、100以上のルールが追加されます。追加されるルールの一覧は、TypeScript ESLintのドキュメントで確認できます。
- 新規プロジェクト
eslint-typescript-tutorialを作成しました。 - TypeScriptをインストールし、
tsconfig.jsonを設定しました。 - 中身が空の
src/helloWorld.tsを作成し、コンパイルしてみました。 - ESLintとTypeScript ESLintをインストールしました。
TypeScript向けのshareable configを導入する
コーディング規約Airbnb JavaScript Style Guideに準拠したshareable configをインストールします。
shellyarn add -D \'eslint-config-airbnb-base@^15' \'eslint-plugin-import@^2' \'eslint-config-airbnb-typescript@^17'
shellyarn add -D \'eslint-config-airbnb-base@^15' \'eslint-plugin-import@^2' \'eslint-config-airbnb-typescript@^17'
eslint-config-airbnb-baseはJavaScript向けのshareable configです。これを上書きして、TypeScript ESLintのルールを追加したり、TypeScriptコンパイラがチェックするためESLintでチェックする必要がないルールを除外する設定を加えるのがeslint-config-airbnb-typescriptです。eslint-plugin-importは依存関係上、導入が必要なパッケージです。
TypeScript ESLintの設定ファイルを作る
TypeScript ESLintを動かすためには、次の2つの設定ファイルを作る必要があります。
- tsconfig.eslint.json
- .eslintrc.js
これらファイルをプロジェクトルートに作成してください。
shelltouch tsconfig.eslint.json .eslintrc.js
shelltouch tsconfig.eslint.json .eslintrc.js
作成後のディレクトリ構造text.├── .eslintrc.js├── dist│ └── helloWorld.js├── node_modules├── package.json├── src│ └── helloWorld.ts├── tsconfig.eslint.json├── tsconfig.json└── yarn.lock
作成後のディレクトリ構造text.├── .eslintrc.js├── dist│ └── helloWorld.js├── node_modules├── package.json├── src│ └── helloWorld.ts├── tsconfig.eslint.json├── tsconfig.json└── yarn.lock
tsconfig.eslint.json
TypeScript ESLintは、チェック時に型情報を利用するために、TypeScriptコンパイラを使います。その際のコンパイラ設定をtsconfig.eslint.jsonに書きます。コンパイラ設定は、tsconfig.jsonの内容をextendsで継承しつつ、上書きが必要なところだけ記述していきます。
tsconfig.eslint.jsonjson{"extends": "./tsconfig.json"}
tsconfig.eslint.jsonjson{"extends": "./tsconfig.json"}
今回は、TypeScriptファイルに加えて、ESLintの設定ファイル.eslintrc.js自体もESLintのチェック対象に含めたいので、allowJsの追加とincludeの上書きをします。
tsconfig.eslint.jsonjson{"extends": "./tsconfig.json","compilerOptions": {"allowJs": true},"include": ["src", ".*.js"]}
tsconfig.eslint.jsonjson{"extends": "./tsconfig.json","compilerOptions": {"allowJs": true},"include": ["src", ".*.js"]}
".*.js"は、.eslintrc.jsなどドット始まりのJSファイルにマッチするパターンです。パターンマッチにしておくことで、将来的に導入される他の設定ファイルもチェック対象に含めるようにできます。
また、テストフレームワーク「Jest」の設定ファイルでは、jest.config.jsのようにドットはじまりでないJSファイルもありえます。このようなファイルが追加されるのを見越して、"*.js"もあらかじめ追加しておくとよいです。
tsconfig.eslint.jsonjson{"extends": "./tsconfig.json","compilerOptions": {"allowJs": true},"include": ["src", ".*.js", "*.js"]}
tsconfig.eslint.jsonjson{"extends": "./tsconfig.json","compilerOptions": {"allowJs": true},"include": ["src", ".*.js", "*.js"]}
このように、TypeScript ESLintでチェックする対象は、includeに追加していく必要があります。
tsconfig.eslint.jsonが正しく設定されているか、次のコマンドを実行して出力を確認してください。
shellnpx tsc --showConfig --project tsconfig.eslint.json
shellnpx tsc --showConfig --project tsconfig.eslint.json
設定が正しいと、次のような出力になるはずです。
text{"compilerOptions": {"outDir": "./dist","allowJs": true},"files": ["./src/helloWorld.ts","./.eslintrc.js"],"include": ["src",".*.js","*.js"]}
text{"compilerOptions": {"outDir": "./dist","allowJs": true},"files": ["./src/helloWorld.ts","./.eslintrc.js"],"include": ["src",".*.js","*.js"]}
.eslintrc.js
次にESLintの設定ファイル.eslintrc.jsを作ります。内容は次のとおりにしてください。
.eslintrc.jsjsmodule .exports = {root : true,parser : "@typescript-eslint/parser",plugins : ["@typescript-eslint"],env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",project : "./tsconfig.eslint.json",tsconfigRootDir :__dirname ,},ignorePatterns : ["dist"],extends : ["airbnb-base","airbnb-typescript/base","plugin:@typescript-eslint/recommended-requiring-type-checking",],rules : {"import/prefer-default-export": "off","@typescript-eslint/quotes": ["error", "double"],},};
.eslintrc.jsjsmodule .exports = {root : true,parser : "@typescript-eslint/parser",plugins : ["@typescript-eslint"],env : {browser : true,es2021 : true,},parserOptions : {ecmaVersion : "latest",sourceType : "module",project : "./tsconfig.eslint.json",tsconfigRootDir :__dirname ,},ignorePatterns : ["dist"],extends : ["airbnb-base","airbnb-typescript/base","plugin:@typescript-eslint/recommended-requiring-type-checking",],rules : {"import/prefer-default-export": "off","@typescript-eslint/quotes": ["error", "double"],},};
root、env、parserOptionsのecmaVersionとsourceTypeについては前のチュートリアルの解説をご覧ください。まだ説明していない、追加のオプションは次で説明します。
parser
jsmodule .exports = {// ...parser : "@typescript-eslint/parser",// ...};
jsmodule .exports = {// ...parser : "@typescript-eslint/parser",// ...};
parserで設定したパーサーを使って、ESLintはJavaScriptやTypeScriptの構文を解析します。上の例では、TypeScriptパーサーを指定しています。この指定がないと、ESLintはTypeScriptを解釈できず、エラーが発生します。
TypeScriptはJavaScriptの構文を拡張した言語です。なので、このパーサーさえ入れておけば、TypeScriptに限らずJavaScriptのこのパーサーひとつで対応できます。要するに、このパーサーひとつで、TypeScriptとJavaScriptのファイルどちらもリントできるようになります。
plugins
jsmodule .exports = {// ...plugins : ["@typescript-eslint"],// ...};
jsmodule .exports = {// ...plugins : ["@typescript-eslint"],// ...};
ESLintは公式が提供するルールに加えて、第三者が作成したルールを使うこともできます。第三者が作成したルールはプラグインという形で公開されています。このpluginsフィールドにプラグインを追加すると、ルールが追加できます。上の例では、TypeScript ESLint独自のルールを追加するために、@typescript-eslintを設定しています。
parserOptions
jsmodule .exports = {// ...parserOptions : {// ...project : "./tsconfig.eslint.json",tsconfigRootDir :__dirname ,},// ...};
jsmodule .exports = {// ...parserOptions : {// ...project : "./tsconfig.eslint.json",tsconfigRootDir :__dirname ,},// ...};
projectとtsconfigRootDirはTypeScript ESLint独自のオプションです。tsconfigRootDirはプロジェクトルートの絶対パスを指定します。projectは、ESLint実行時に使うコンパイラ設定ファイルをtsconfigRootDirからの相対パスで指定します。これらの設定は、TypeScript ESLintが型情報を参照するために必要な設定です。
ignorePatterns
jsmodule .exports = {// ...ignorePatterns : ["dist"],// ...};
jsmodule .exports = {// ...ignorePatterns : ["dist"],// ...};
ignorePatternsはESLintのチェック対象外にするファイルやディレクトリを指定するオプションです。TypeScriptプロジェクトでは、コンパイルで生成されるJavaScriptは、リントしないのが普通です。なので、distディレクトリをチェック対象外にしておきます。
extends
jsmodule .exports = {// ...extends : ["airbnb-base", // ①"airbnb-typescript/base", // ②"plugin:@typescript-eslint/recommended-requiring-type-checking", // ③],// ...};
jsmodule .exports = {// ...extends : ["airbnb-base", // ①"airbnb-typescript/base", // ②"plugin:@typescript-eslint/recommended-requiring-type-checking", // ③],// ...};
extendsはshareable configを使うための設定です。①は、JavaScript向けのルールです。これを拡張してTypeScript ESLintのルールにも範囲を広げたのが②です。①と②は上の順番でないと正しく設定されないので注意してください。
③はTypeScript ESLintが提供する推奨ルールセットで、型情報を要するルールを含みます。このルールセットでどのルールが有効になるかは、公式ドキュメントをご覧ください。
rules
jsmodule .exports = {// ...rules : {"import/prefer-default-export": "off","@typescript-eslint/quotes": ["error", "double"],},// ...};
jsmodule .exports = {// ...rules : {"import/prefer-default-export": "off","@typescript-eslint/quotes": ["error", "double"],},// ...};
ここのrulesは、shareable configで有効化されたルールを上書きするのに用いています。TypeScript ESLintで追加されたルールは、@typescript-eslint/が接頭辞になります。
- コーディング規約Airbnb JavaScript Style Guideに準拠したshareable configをインストールしました。
- TypeScript ESLintの設定ファイルを作りました。
- tsconfig.eslint.json
- .eslintrc.js
TypeScriptをチェックする
TypeScript ESLintを使う準備ができたので、いよいよTypeScriptをチェックしてみたいと思います。
まず、空だったsrc/helloWorld.tsに次のコードを書いて保存してください。
src/helloWorld.tstsexport consthello_world = "Hello World";console .log (hello_world );
src/helloWorld.tstsexport consthello_world = "Hello World";console .log (hello_world );
そうしたら、ESLintを実行してみましょう。
shellnpx eslint .
shellnpx eslint .
すると、次の結果が出力されるはずです。
2つの問題点が報告されています。1つ目は、変数名の命名規則が守られていない点についてのエラーです。2つ目は、console.logが使われている点についての警告です。
これらの問題点を修正してみましょう。src/helloWorld.tsを次の内容に変更し、保存してください。
src/helloWorld.tstsexport consthelloWorld = "Hello World";
src/helloWorld.tstsexport consthelloWorld = "Hello World";
再びESLintを実行して、問題点が解消されているか確認してみましょう。
shellnpx eslint .
shellnpx eslint .
出力結果に何も表示されていなければ、問題点が解決されています。
以上で、ESLintでTypeScriptをリントするチュートリアルは終わりです。
VS CodeとESLintを統合しよう
ここでは、Visual Studio Code(VS Code)に、ESLintを組み込む方法を説明します。
ESLintはコマンドひとつでコーディング規約をチェックできるようになり、それだけでも便利です。しかし、VS CodeとESLintを統合するとさらに便利になります。コードを書いているときに、リアルタイムで問題点のフィードバックが得られるようになるからです。

VS CodeとESLintを統合するには、ESLintの拡張をVisual Studio Codeのマーケットプレイスからインストールするだけです。

JetBrains IDEとESLintを統合しよう
ここでは、WebStormなどのJetBrains IDEに、ESLintを組み込む方法を説明します。
ESLintはコマンドひとつでコーディング規約をチェックできるようになり、それだけでも便利です。しかし、JetBrains IDEとESLintを統合するとさらに便利になります。コードを書いているときに、リアルタイムで問題点のフィードバックが得られるようになるからです。

WebStormは、ESLint統合機能がデフォルトで入っているので、プラグインなどをインストールする必要はありません。ESLintを有効にするには、「Preferences」を開き、検索に「eslint」と入力します(①)。絞り込まれたメニューから「ESLint」を開きます(②)。「Automatic ESLint configuration」にチェックを入れます(③)。最後に「OK」を押すと設定完了です(④)。
