TypeScript を使い始めると、型エラーは解消できてもコードスタイルのばらつきや危険なパターンの混入を防ぐ手段が必要になります。そこで欠かせないのが ESLint(コード品質の静的解析)とPrettier(コードフォーマット)の組み合わせです。
特に @typescript-eslint は TypeScript の型情報を解析に利用できるため、「await の付け忘れ」「switch の網羅漏れ」など、実行してみないとわからないバグをコンパイル前に検出できます。
この記事では ESLint 9.x(Flat Config)を中心に、Prettier との連携・フレームワーク別設定・VSCode 自動整形・CI 設定まで一気通貫で解説します。
- ESLint 9.x(Flat Config)と @typescript-eslint v8 の基本セットアップ
- 推奨ルール(recommended / strict / stylistic)の違いと選び方
- 型チェックが必要なルール(
no-floating-promises等)の設定方法 - 重要なルール 12 個の詳細解説(NG/OK コード付き)
- Prettier との連携(
eslint-config-prettier) - import 順序の自動整列(
eslint-plugin-simple-import-sort) - React / Next.js 向け追加設定
- VSCode での自動整形設定
- GitHub Actions(CI)への組み込み
- ESLint 9.x(Flat Config)+
typescript-eslintv8.x - Node.js 20 以上(
import.meta.dirnameは Node 20.11+ が必要。18系の場合は記事内の代替コードを参照) - TypeScript 5.x
ESLint 8.x(.eslintrc.json 形式)をお使いの場合は「ESLint 8.x での設定」セクションを参照してください。
- ESLint と Prettier の役割の違い
- インストールと基本設定(ESLint 9 + Flat Config)
- @typescript-eslint のルールセット選択
- 重要なルール詳細解説
- @typescript-eslint/no-explicit-any
- @typescript-eslint/no-floating-promises(型チェック必須)
- @typescript-eslint/no-misused-promises(型チェック必須)
- @typescript-eslint/switch-exhaustiveness-check(型チェック必須)
- @typescript-eslint/consistent-type-imports
- @typescript-eslint/no-non-null-assertion
- @typescript-eslint/prefer-nullish-coalescing
- @typescript-eslint/no-unused-vars
- @typescript-eslint/restrict-template-expressions
- Prettier の設定
- フレームワーク別追加設定
- ESLint 8.x での設定(レガシー)
- package.json スクリプトの設定
- VSCode との連携設定
- GitHub Actions(CI)への組み込み
- よくあるエラーと解消法
- よくある質問
- まとめ
ESLint と Prettier の役割の違い
まず両者の役割を明確にしておきましょう。混同しがちですが、目的がまったく異なります。
| ツール | 役割 | 検出例 |
|---|---|---|
| ESLint | コード品質の静的解析・バグの早期発見 | await 付け忘れ、any の多用、未使用変数 |
| Prettier | コードの見た目を統一するフォーマッター | インデント・引用符・末尾カンマ・行の折り返し |
かつては ESLint の
--fix でスペースやインデントを整えることもありましたが、現在の @typescript-eslint はフォーマット系ルールを非推奨化しています。フォーマットは Prettier に完全に委譲し、ESLint はコード品質の検出に集中させるのが現代のベストプラクティスです。インストールと基本設定(ESLint 9 + Flat Config)
パッケージのインストール
# ESLint 本体 + @eslint/js(recommended ルールセット) npm install --save-dev eslint @eslint/js # typescript-eslint(パーサー + プラグイン がこのパッケージ1つに統合) npm install --save-dev typescript-eslint # Prettier + ESLint との競合ルールを無効化するパッケージ npm install --save-dev prettier eslint-config-prettier # import 順序の自動整列(オプション) npm install --save-dev eslint-plugin-simple-import-sort
eslint.config.mjs の作成
// eslint.config.mjs(プロジェクトルートに配置)
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import prettier from "eslint-config-prettier";
import simpleImport from "eslint-plugin-simple-import-sort";
export default tseslint.config(
// ── 無視するパス ──
{ ignores: ["node_modules/", "dist/", ".next/", "coverage/"] },
// ── ESLint 推奨ルール ──
eslint.configs.recommended,
// ── @typescript-eslint 推奨ルール(型チェック付き)──
...tseslint.configs.recommendedTypeChecked,
...tseslint.configs.stylisticTypeChecked,
// ── TypeScript パーサー設定 ──
{
languageOptions: {
parser: tseslint.parser,
parserOptions: {
project: true, // tsconfig.json を自動検出
tsconfigRootDir: import.meta.dirname, // Node.js 20.11+ で利用可
// Node.js 18 の場合: path.dirname(fileURLToPath(import.meta.url))
},
},
},
// ── カスタムルール ──
{
plugins: {
"simple-import-sort": simpleImport,
},
rules: {
// import 順序の自動整列
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
// @typescript-eslint のカスタム設定
"@typescript-eslint/no-explicit-any": "warn", // any を警告(禁止なら "error")
"@typescript-eslint/consistent-type-imports": "error", // import type を強制
"@typescript-eslint/no-non-null-assertion": "warn", // ! 演算子を警告
"@typescript-eslint/explicit-function-return-type": "off", // 戻り値型は推論に任せる場合
// 型チェックが必要なルール(重要)
"@typescript-eslint/no-floating-promises": "error", // await忘れを検出
"@typescript-eslint/no-misused-promises": "error", // Promise の誤用を検出
"@typescript-eslint/switch-exhaustiveness-check": "error", // switch の網羅漏れを検出
},
},
// ── Prettier(競合するフォーマットルールをすべて無効化)──
// ※ 必ず最後に配置すること
prettier,
);
tseslint.config() は通常の ESLint 設定配列をラップしたユーティリティ関数です。型補完が効く・spread不要でextends相当が書ける・ルール名の補完が効くという利点があり、生の設定配列より安全に記述できます。プレーンな配列 export default [...] でも動作しますが、tseslint.config() の使用を推奨します。@typescript-eslint のルールセット選択
typescript-eslint は複数のルールセットを提供しています。プロジェクトの要件に合わせて選択してください。
| ルールセット名 | 厳しさ | 型チェック | 用途 |
|---|---|---|---|
recommended |
★★☆ | なし | 型チェック不要・CI負荷を下げたい |
recommendedTypeChecked |
★★☆ | あり | バランス重視・多くのプロジェクトの標準 |
strict |
★★★ | なし | より厳しく、型チェック不要 |
strictTypeChecked |
★★★ | あり | 型安全性を最大化したい本番プロジェクト |
stylistic |
— | なし | コードスタイルの統一(recommended と併用) |
stylisticTypeChecked |
— | あり | スタイル統一・型チェック版 |
TypeChecked 系ルールは TypeScript の型解析(tsconfig.json 経由)を必要とするため、大規模なプロジェクトでは Lint の実行時間が数倍になる場合があります。CI では tsc --noEmit と eslint を並列実行するか、TIMING=1 eslint . でボトルネックを特定してください。速度を優先する場合は recommended(型チェックなし)を使い、no-floating-promises など必要なルールだけ個別に有効化するアプローチも有効です。重要なルール詳細解説
@typescript-eslint/no-explicit-any
any の使用を検出します。型安全性の根幹を守るルールです。
// NG: any を直接使用
function parse(data: any) {
return data.value; // 型チェックが無効化される
}
// OK: unknown を使って型を絞り込む
function parse(data: unknown) {
if (typeof data === "object" && data !== null && "value" in data) {
return (data as { value: string }).value;
}
throw new Error("Invalid data");
}
// OK(やむを得ない場合): eslint-disable コメントで個別に無効化
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function legacyFn(data: any) { ... }
unknown と any の違いはTypeScript unknown・any・never 完全ガイドを参照してください。
@typescript-eslint/no-floating-promises(型チェック必須)
戻り値が Promise の関数を await せずに呼び出した場合に検出します。非同期処理のエラーが握りつぶされる最も危険なバグのひとつです。
// NG: await せずに Promise を捨てている(エラーが検出されない)
async function saveUser(user: User) {
prisma.user.create({ data: user }); // ← await 忘れ!
return "saved";
}
// NG: then/catch もない
fetchData(); // Promise が宙に浮く
// OK: await する
async function saveUser(user: User) {
await prisma.user.create({ data: user });
return "saved";
}
// OK: 意図的に待たない場合は void を付ける
void fetchData(); // ESLint に「意図的」と明示
@typescript-eslint/no-misused-promises(型チェック必須)
Promise が期待されない場所に渡してしまうパターンを検出します。
// NG: if 条件に async 関数を渡す(常に truthy になる)
if (checkUser()) { // checkUser が async function なら Promise を返す
// ...
}
// NG: イベントハンドラに async 関数を直接渡す
// React だと onClick={async () => await doSomething()} は問題ないが
// 一部の非対応 API では Promise が無視される
element.addEventListener("click", async () => {
await doSomething(); // エラーが握りつぶされる可能性
});
// OK: 同期ラッパーでくるむ
element.addEventListener("click", () => {
void doSomething().catch(console.error);
});
// OK: 条件は明示的な Promise 評価にする
if (await checkUser()) {
// ...
}
@typescript-eslint/switch-exhaustiveness-check(型チェック必須)
Union 型や enum に対する switch 文で、すべてのケースが網羅されているかチェックします。新しい値が追加されたときに対応漏れを防ぐ非常に重要なルールです。
type Status = "pending" | "approved" | "rejected";
// NG: "rejected" ケースが欠けている
function getLabel(status: Status): string {
switch (status) {
case "pending": return "審査中";
case "approved": return "承認済み";
// "rejected" が漏れているが、TS コンパイラはエラーにしない
default: return "不明";
}
}
// OK: すべてのケースを網羅(default 不要になる)
function getLabel(status: Status): string {
switch (status) {
case "pending": return "審査中";
case "approved": return "承認済み";
case "rejected": return "却下";
// TS が "rejected" を追加したとき、このルールがエラーを出す
}
}
// OK: default を残す場合は never チェックで網羅性を担保
function assertNever(x: never): never {
throw new Error("Unexpected value: " + x);
}
function getLabel(status: Status): string {
switch (status) {
case "pending": return "審査中";
case "approved": return "承認済み";
case "rejected": return "却下";
default: return assertNever(status);
}
}
switch 文と Discriminated Unions の詳細は判別可能なユニオン型完全ガイドを参照してください。
@typescript-eslint/consistent-type-imports
型だけを使う import では import type の使用を強制します。import type はバンドル時に削除されるため、バンドルサイズ削減と循環参照の防止に効果があります。
// NG: 型のみを使う場合でも通常 import
import { User, Post } from "@prisma/client";
import { Router } from "express";
// OK: 型のみなら import type
import type { User, Post } from "@prisma/client";
import type { Router } from "express";
// OK: 値と型を混在させる場合(inline type)
import { prisma, type User } from "./lib/prisma";
// ^^^^ type キーワードで個別指定
@typescript-eslint/no-non-null-assertion
Non-null アサーション演算子(!)の使用を検出します。! は TypeScript の型チェックを強制的にスキップするため、実行時エラーの原因になります。
// NG: ! で null チェックを強制スキップ
const user = getUser()!; // getUser() が null を返すと実行時エラー
const el = document.getElementById("app")!; // null の可能性
// OK: 明示的な null チェック
const user = getUser();
if (user === null) throw new Error("User not found");
user.name; // ここでは User 型
// OK: Optional Chaining で安全にアクセス
const el = document.getElementById("app");
el?.classList.add("loaded");
// OK(やむを得ない場合): コメントで意図を明示
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const el = document.getElementById("app")!; // index.html に必ず存在
@typescript-eslint/prefer-nullish-coalescing
|| の代わりに ??(Nullish Coalescing)の使用を推奨します。|| は 0 や空文字 "" も falsy として扱うため、意図しないデフォルト値の適用が起きやすいです。
// NG: || は 0 や "" を falsy として扱う const count = user.postCount || 10; // postCount が 0 なら 10 になってしまう! const name = user.name || "名無し"; // name が "" なら "名無し" になってしまう! // OK: ?? は null/undefined のみフォールバック const count = user.postCount ?? 10; // 0 はそのまま 0 const name = user.name ?? "名無し"; // "" はそのまま ""
@typescript-eslint/no-unused-vars
標準の no-unused-vars は TypeScript の型エラーを適切に処理できないため、@typescript-eslint 版に置き換えます。
// eslint.config.mjs での設定
{
rules: {
"no-unused-vars": "off", // 標準ルールを無効化
"@typescript-eslint/no-unused-vars": ["error", {
argsIgnorePattern: "^_", // _prefix で始まる引数を無視
varsIgnorePattern: "^_", // _prefix で始まる変数を無視
caughtErrorsIgnorePattern: "^_", // catch (_e) を無視
ignoreRestSiblings: true, // rest で残りを無視する場合
}],
}
}
// 使用例: _ プレフィクスで意図的に未使用を明示
const [_first, second] = items; // _first は意図的に無視
try { ... } catch (_e) { ... } // エラーオブジェクトを使わない場合
function fn(_req: Request, res: Response) { ... } // req を使わない Express ハンドラ
@typescript-eslint/restrict-template-expressions
テンプレートリテラルの中に any や object 型を埋め込むことを防ぎます。
// NG: object をそのまま埋め込むと "[object Object]" になる
const user = { name: "Alice" };
const msg = `ユーザー: ${user}`; // → "ユーザー: [object Object]"
// OK: 文字列に変換する
const msg = `ユーザー: ${user.name}`;
const msg = `ユーザー: ${JSON.stringify(user)}`;
Prettier の設定
prettier.config.mjs の作成
// prettier.config.mjs
/** @type {import("prettier").Config} */
export default {
semi: true, // セミコロンあり
singleQuote: false, // ダブルクォート(TypeScript 標準)
tabWidth: 2, // インデント 2 スペース
trailingComma: "all", // 末尾カンマ(ES5+ に対応)
printWidth: 100, // 1行の最大文字数
arrowParens: "always", // アロー関数の引数にカッコ((x) => x)
endOfLine: "lf", // 改行コード(Git 管理に LF を推奨)
// TypeScript / JSX の設定
plugins: [], // 必要に応じて prettier-plugin-tailwindcss 等を追加
};
.prettierignore の作成
# .prettierignore node_modules/ dist/ .next/ coverage/ *.min.js *.min.css package-lock.json pnpm-lock.yaml
eslint.config.mjs で prettier(eslint-config-prettier)は必ず設定配列の最後に配置してください。後に書かれた設定が前の設定を上書きするため、最後に置かないと Prettier と競合する ESLint ルールが残ります。(上記の eslint.config.mjs サンプルはこの順序を守っています。)フレームワーク別追加設定
React プロジェクト
# React 向け ESLint プラグイン npm install --save-dev eslint-plugin-react eslint-plugin-react-hooks
// eslint.config.mjs(React 追加設定)
import reactHooks from "eslint-plugin-react-hooks";
import react from "eslint-plugin-react";
export default tseslint.config(
// ... 基本設定 ...
{
plugins: {
"react": react,
"react-hooks": reactHooks,
},
rules: {
...react.configs.recommended.rules,
...reactHooks.configs.recommended.rules,
"react/react-in-jsx-scope": "off", // React 17+ は import 不要
"react/prop-types": "off", // TypeScript が型チェックするため不要
"react-hooks/exhaustive-deps": "warn",
},
settings: {
react: { version: "detect" }, // インストール済みの React version を自動検出
},
},
);
Next.js プロジェクト
# Next.js 公式 ESLint プラグイン(create-next-app で自動インストール済み) npm install --save-dev @next/eslint-plugin-next
// eslint.config.mjs(Next.js 追加設定)
import nextPlugin from "@next/eslint-plugin-next";
export default tseslint.config(
// ... 基本設定 ...
{
plugins: {
"@next/next": nextPlugin,
},
rules: {
...nextPlugin.configs.recommended.rules,
...nextPlugin.configs["core-web-vitals"].rules,
},
},
);
ESLint 8.x での設定(レガシー)
既存プロジェクトで ESLint 8.x を使っている場合の設定です。新規プロジェクトは ESLint 9.x の Flat Config を推奨します。
# ESLint 8.x 用のパッケージ(9.x とは異なる) npm install --save-dev eslint@8 npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin npm install --save-dev prettier eslint-config-prettier
// .eslintrc.json(ESLint 8.x 用)
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json",
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended-type-checked",
"plugin:@typescript-eslint/stylistic-type-checked",
"prettier"
],
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/consistent-type-imports": "error"
},
"ignorePatterns": ["dist/", "node_modules/"]
}
package.json スクリプトの設定
// package.json
{
"scripts": {
// Lint: エラーを検出して終了コードを返す
"lint": "eslint .",
"lint:fix": "eslint . --fix",
// Format: Prettier でファイルを整形
"format": "prettier --write .",
"format:check": "prettier --check .", // CI 向け(整形が必要なら失敗)
// 型チェック: TypeScript コンパイルせず型のみ検査
"typecheck": "tsc --noEmit",
// 全チェック: CI で使う
"check": "npm run typecheck && npm run lint && npm run format:check"
}
}
VSCode との連携設定
拡張機能のインストール
以下の VSCode 拡張機能を追加してください。
- ESLint(
dbaeumer.vscode-eslint)— ESLint をリアルタイム表示 - Prettier – Code formatter(
esbenp.prettier-vscode)— Prettier でフォーマット
.vscode/settings.json
// .vscode/settings.json(プロジェクト全員で共有)
{
// ファイル保存時に自動整形
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
// ファイル保存時に ESLint --fix を自動実行
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
// TypeScript・JavaScriptで Prettier をデフォルトフォーマッターに設定
"[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[typescriptreact]":{ "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[javascriptreact]":{ "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
// ESLint の作業ディレクトリを指定(モノレポの場合)
// "eslint.workingDirectories": ["./packages/app", "./packages/api"],
// import type の自動挿入
"typescript.preferences.preferTypeOnlyAutoImports": true
}
.vscode/extensions.json(推奨拡張機能)
// .vscode/extensions.json(git にコミットしてチームで共有)
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-vscode.vscode-typescript-next"
]
}
GitHub Actions(CI)への組み込み
# .github/workflows/lint.yml
name: Lint & Type Check
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install dependencies
run: npm ci
# 型チェック・Lint・フォーマットチェックを並列実行
- name: Type check
run: npm run typecheck
- name: ESLint
run: npm run lint
- name: Prettier check
run: npm run format:check
husky + lint-staged を使うと、git commit 時に変更ファイルだけ Lint・Format を自動実行できます:npm install --save-dev husky lint-stagednpx husky init.husky/pre-commit に npx lint-staged を追加し、package.json に "lint-staged": { "*.{ts,tsx}": ["eslint --fix", "prettier --write"] } を設定します。CI に到達する前にローカルで問題を修正できます。よくあるエラーと解消法
「Parsing error: “parserOptions.project” has been set…」
ESLint がスキャンしたファイルが tsconfig.json の include に含まれていない場合に発生します。
// 解決策1: eslint.config.mjs に ignores を追加
{ ignores: ["*.js", "*.mjs", "*.cjs"] } // 設定ファイル自身も対象になりうる
// 解決策2: tsconfig.eslint.json を作成して ESLint 専用の tsconfig を指定
{
"extends": "./tsconfig.json",
"include": ["**/*.ts", "**/*.tsx", "*.mjs"] // 設定ファイルも含める
}
// eslint.config.mjs で参照
parserOptions: {
project: "./tsconfig.eslint.json",
}
「Delete `·` Prettier/prettier」エラー(CRLF vs LF)
Windows 環境で Git の autocrlf が true になっていると、チェックアウト時に CRLF に変換され、Prettier の LF 設定と競合します。
# .gitattributes(リポジトリルート) * text=auto eol=lf # または Git の設定 git config --global core.autocrlf false
型チェックルールが遅すぎる場合
// 解決策: TypeChecked ルールセットを外し、必要なものだけ有効化
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended, // TypeChecked なし版
{
languageOptions: {
parser: tseslint.parser,
parserOptions: {
project: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
// 型チェックが必要なルールを個別に有効化
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": "error",
"@typescript-eslint/switch-exhaustiveness-check": "error",
},
},
);
よくある質問
QESLint 9(Flat Config)と ESLint 8(.eslintrc)どちらを選べばよいですか?
A新規プロジェクトなら ESLint 9 の Flat Config を選んでください。TypeScript による型補完が効く・eslint.config.mjs 1ファイルに設定が集約される・.eslintignore が不要になる(ignores で設定)など利点が多いです。既存プロジェクトで ESLint 8 を使っている場合は @eslint/migrate-config でFlat Config に自動変換できます(npx @eslint/migrate-config .eslintrc.json)。
QrecommendedTypeChecked と strictTypeChecked の違いは?
Arecommended は安全性とエルゴノミクスのバランスを重視し、ほとんどのプロジェクトで問題なく使えます。strict はより多くのルールが error に設定され、any の検出や null チェックの精度が上がりますが、既存コードへの適用時に大量の修正が必要になります。新規プロジェクトなら strictTypeChecked から始めるのが理想です。
QBiome や oxlint など ESLint 以外の選択肢はどうですか?
ABiome(旧 Rome)と oxlint は Rust 製で ESLint より数十倍高速です。ただし @typescript-eslint の型チェックルール(no-floating-promises 等)は2026 年時点で Biome には実装されていません。速度優先なら Biome を基本 Linter として使い、型チェックルールだけ ESLint を併用するハイブリッド運用も選択肢です。新規プロジェクトでは Biome の進化状況も確認しつつ判断するとよいでしょう。
Qeslint-disable コメントを多用しています。問題ありますか?
A// eslint-disable-next-line の多用は「ルールが実態に合っていない」サインです。理由なく無効化している場合はルール設定を見直してください(例: "warn" に下げる)。やむを得ない場合はコメントで理由を書く運用にしましょう:// eslint-disable-next-line @typescript-eslint/no-explicit-any -- 外部ライブラリの型が不完全なため。@typescript-eslint/ban-ts-comment を使うと @ts-ignore に理由を必須化できます。
Qモノレポ(Turborepo / Nx)での ESLint 設定はどうすればよいですか?
A各パッケージに eslint.config.mjs を置き、共通設定は @内部パッケージ(例: @myapp/eslint-config)に切り出してください。ルートの eslint.config.mjs に { ignores: ["packages/*/dist/"] } を設定し、Turborepo の場合は turbo.json のタスクに lint を追加して変更パッケージだけ Lint するキャッシュ戦略を組みます。
まとめ
TypeScript プロジェクトへの ESLint + Prettier 導入のポイントをまとめます。
| 設定項目 | ポイント |
|---|---|
| パッケージ選択 | ESLint 9 なら typescript-eslint(統合パッケージ)1つで完結 |
| ルールセット | recommendedTypeChecked + stylisticTypeChecked が現代の標準 |
| 型チェックルール | no-floating-promises・switch-exhaustiveness-check は必ず有効化 |
| Prettier | eslint-config-prettier を設定の最後に配置 |
| VSCode | formatOnSave + source.fixAll.eslint で保存時に自動修正 |
| CI | tsc --noEmit・eslint・prettier --check の3つを並列で検証 |
ESLint の設定に加えて、TypeScript 自体の厳格な設定はtsconfig.json 完全ガイドを、JavaScript から TypeScript への移行手順はTypeScript 移行ガイドをあわせて参照してください。