TypeScript 與 ESLint 整合教學:使用 @typescript-eslint 建立乾淨、可維護的程式碼
簡介
在現代前端開發中,TypeScript 已成為大型專案的事實標準,提供靜態型別檢查、智能提示與更好的重構支援。然而,僅靠 TypeScript 的型別系統並不能完整保證程式碼風格與潛在錯誤的檢測。這時 ESLint 便扮演了重要角色:它是一套高度可客製化的靜態分析工具,能在編寫階段即捕捉語法錯誤、潛在 bug 以及不一致的程式碼風格。
把 ESLint 與 TypeScript 結合,最常見且官方推薦的方式就是使用 @typescript-eslint 系列套件。透過這個套件,我們可以讓 ESLint 完全理解 TypeScript 的語法與型別資訊,同時使用大量專為 TypeScript 設計的規則,讓程式碼在 可讀性、一致性 與 安全性 上都有明顯提升。
本篇文章將一步步說明如何在專案中安裝、設定與運用 @typescript-eslint,並提供實用範例、常見陷阱與最佳實踐,協助你在日常開發中即時得到高品質的回饋。
核心概念
1. 為什麼需要 @typescript-eslint?
- ESLint 原生只支援 JavaScript:直接套用在
.ts檔案上時,會因為語法差異(如介面、型別別名)產生大量誤報。 - @typescript-eslint 把 TypeScript AST 轉成 ESLint 可理解的結構:它提供兩個主要套件
@typescript-eslint/parser:解析 TypeScript 程式碼。@typescript-eslint/eslint-plugin:一組針對 TypeScript 設計的規則(如no-unused-vars的型別感知版)。
- 型別感知規則:能根據型別資訊判斷是否真的未使用、是否安全使用
any、或是是否違反了「嚴格的 null 檢查」等。
2. 安裝步驟
在一個已經安裝 typescript 與 eslint 的專案中,執行以下指令:
npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin
# 或者使用 Yarn
yarn add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
⚠️ 小提醒:若專案尚未安裝
eslint,請先npm i -D eslint,再進行上述安裝。
3. 基本設定檔 (.eslintrc.js)
以下是一個最小可運作的設定範例,說明如何告訴 ESLint 使用 TypeScript 解析器與插件:
module.exports = {
parser: '@typescript-eslint/parser', // 使用 TypeScript 解析器
parserOptions: {
ecmaVersion: 2020, // 允許最新的 ECMAScript 語法
sourceType: 'module',
project: './tsconfig.json', // 讓 parser 能讀取型別資訊
},
plugins: ['@typescript-eslint'],
extends: [
'eslint:recommended', // 基本的 ESLint 建議規則
'plugin:@typescript-eslint/recommended', // @typescript-eslint 推薦規則
],
rules: {
// 你可以在此覆寫或自行新增規則
'@typescript-eslint/explicit-function-return-type': 'off',
},
};
重點:
parserOptions.project必須指向正確的tsconfig.json,否則型別感知規則會失效,且在大型專案中可能需要設定tsconfig.eslint.json只包含編譯需要的檔案。
4. 常用規則說明
| 規則 | 功能 | 建議設定 |
|---|---|---|
@typescript-eslint/no-unused-vars |
偵測未使用的變數、參數,支援型別資訊 | warn |
@typescript-eslint/explicit-module-boundary-types |
要求匯出函式或類別的參數與回傳型別 | error(視團隊需求) |
@typescript-eslint/no-explicit-any |
禁止直接使用 any |
warn |
@typescript-eslint/strict-boolean-expressions |
嚴格檢查布林表達式,避免隱式轉型 | error |
@typescript-eslint/prefer-nullish-coalescing |
建議使用 ?? 取代 ` |
程式碼範例
以下示範 4 個在實務開發中常見的情境,說明如何透過 @typescript-eslint 捕捉問題並提供修正建議。
1️⃣ 未使用的變數(no-unused-vars)
// src/example1.ts
function compute(a: number, b: number) {
const result = a + b;
const debug = true; // ← 未使用,會被 eslint 報錯
return result;
}
ESLint 產出
error 'debug' is assigned a value but never used @typescript-eslint/no-unused-vars
修正方式:移除或使用該變數,或在開發階段暫時註解掉。
2️⃣ 隱式的 any(no-explicit-any)
// src/example2.ts
function fetchData(url: string): any { // ← 直接使用 any
// 省略實作
}
ESLint 產出
warn Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
改寫建議:
interface ApiResponse {
data: unknown;
status: number;
}
function fetchData(url: string): Promise<ApiResponse> {
// 正式實作
}
3️⃣ 函式回傳型別缺失(explicit-module-boundary-types)
// src/example3.ts
export function add(a: number, b: number) {
return a + b; // 回傳型別隱式為 number,若設定為 error 會被提示
}
ESLint 產出
error Missing return type on function @typescript-eslint/explicit-module-boundary-types
修正:
export function add(a: number, b: number): number {
return a + b;
}
4️⃣ 布林表達式的嚴格檢查(strict-boolean-expressions)
// src/example4.ts
function isValid(value: string | null | undefined) {
if (value) { // 這裡會被 strict-boolean-expressions 警告
return true;
}
return false;
}
ESLint 產出
error Expected a conditional expression and instead saw 'value' @typescript-eslint/strict-boolean-expressions
改寫:
function isValid(value: string | null | undefined) {
if (value != null && value !== '') {
return true;
}
return false;
}
常見陷阱與最佳實踐
| 陷阱 | 說明 | 解決方案 |
|---|---|---|
| parserOptions.project 錯誤 | 若指向錯誤的 tsconfig.json,型別感知規則會失效或報錯「Cannot read file」 |
為 ESLint 建立專屬的 tsconfig.eslint.json,只包含需要 lint 的檔案 |
| 規則衝突 | 同時使用 eslint:recommended 與 plugin:@typescript-eslint/recommended-requiring-type-checking 時,部分規則會重複或衝突 |
先以 plugin:@typescript-eslint/recommended 為基礎,逐一挑選需要的 requiring‑type‑checking 規則 |
| 過度嚴格導致開發阻礙 | 開啟所有 strict 規則會在早期專案造成大量錯誤 |
先採取 warn 等級,等團隊熟悉後逐步升級為 error |
忽略 eslintignore |
未將產生的 dist/、node_modules/ 等目錄加入忽略,會導致不必要的 lint 時間 |
在根目錄建立 .eslintignore,列出 dist/, build/, coverage/ 等 |
未同步更新 eslint、@typescript-eslint 版本 |
版本不匹配可能出現解析錯誤或規則失效 | 使用相容表(官方 README)或 npm outdated 定期檢查升級 |
最佳實踐
- 分層設定:在 monorepo 中,根目錄使用最寬鬆的規則,子套件根據需求覆寫。
- CI 整合:將
eslint . --ext .ts,.tsx加入 GitHub Actions / GitLab CI,確保每次 PR 都通過 lint。 - 自動修正:使用
eslint --fix或在 IDE 中開啟「保存時自動修正」功能,減少手動調整。 - 結合 Prettier:若同時使用 Prettier,請安裝
eslint-config-prettier以關閉衝突的格式化規則。
npm i -D prettier eslint-config-prettier
// .eslintrc.js
extends: [
'plugin:@typescript-eslint/recommended',
'prettier', // 放在最後,確保 Prettier 規則覆蓋 ESLint
],
實際應用場景
1. 大型企業前端團隊
在多個子專案、共用 UI 元件庫的環境中,統一的 lint 規則 能保證所有開發者寫出的程式碼遵循相同的風格與安全標準。透過 @typescript-eslint,團隊可以:
- 強制所有公開 API 必須明確宣告型別,避免意外的
any流出。 - 捕捉未使用的 import,減少打包體積。
- 在 CI 中自動阻止未通過的 PR,減少程式碼審查成本。
2. 開源套件維護者
當維護一個開源的 TypeScript 套件時,使用 @typescript-eslint 可以:
- 讓貢獻者在本地快速得到回饋,減少維護者的審核工作。
- 配合
typedoc產生文件,確保程式碼與文件同步,因為未使用的變數或錯誤的型別會被即時指出。
3. 教育與培訓
在教學環境中,透過 即時 lint(IDE 插件或 eslint --watch)可以讓學員在寫程式的同時學會:
- 正確的型別宣告方式。
- 常見的 JavaScript/TypeScript 錯誤(例如隱式布林轉型)。
- 何時應該使用
unknown而非any。
總結
- @typescript-eslint 是連接 ESLint 與 TypeScript 的橋樑,讓靜態分析不僅能檢查語法,更能感知型別資訊。
- 只要安裝
@typescript-eslint/parser與@typescript-eslint/eslint-plugin,並在.eslintrc中正確設定parserOptions.project,就能即時得到 未使用變數、any、回傳型別缺失 等高價值回饋。 - 在實務上,避免過度嚴格、設定正確的忽略檔案、結合 Prettier 與 CI,能讓 lint 成為開發流程的自然環節,而非阻礙。
- 無論是大型企業、開源專案或是教學環境,使用 @typescript-eslint 都能提升程式碼品質、降低維護成本,讓團隊更專注於功能本身。
行動建議:今天就把上述設定套用到你的專案,執行
npm run lint -- --fix,感受即時回饋的力量,讓 TypeScript 程式碼在品質與可讀性上都得到顯著提升吧!