[note] ESLint
keywords: CLI, linted
- Configuring ESLint @ ESLint > UserGuide > Configuring
- Configuration Files @ ESLint > UserGuide > Configuration
- ESLint Demo
ESLint v9 後的 API 有 breaking change,使用的是「flat configuration」,請在使用前先確認專案使用的 ESLint 版本。
Command Line Interface
$ npm init @eslint/config@latest
# npx eslint [options] [file|dir|glob]*
$ npx eslint yourfile.js
$ npx eslint file1.js file2.js
$ npx eslint "lib/**"
$ npx eslint # 等同於 npx eslint .
# Debug
npx eslint --print-config file.js # 使用時機:當你不確定為什麼 linting 沒有產生預期的結果
npx eslint --inspect-config # 使用時機:當你不確定某個檔案是否有套用到特定的 configuration object
ESLint Configuration
// eslint.config.js
import exampleConfigs from 'eslint-config-example';
export default [
{
/**
* Globally Ignore these files
* 如果在 config object 中只使用 ignores 而沒有其他設定,
* 那麼這些 patterns 將會被當作全域的 ignores
*/
ignores: [
'dist',
'src/lib/api/schema.ts', // auto-generated by openapi-typescript
],
},
/**
* Cascading Configuration Objects
* 如果對於特定的檔案,有多個 config object 符合,
* 那麼這些 config object 會被合併,
* 當有衝突時後面的 object 會覆蓋前面的 object
*/
{
/**
* files 用來指定這個 config object 要套用的檔案 pattern。
* 如果這個 config object 沒有指定 files,
* 則這個 config object 的設定會作用在所有其他 config object 中有設定的 files 上,
* 類似 global configuration。
*/
files: ['**/*.js'],
linterOptions: {
reportUnusedDisableDirectives: 'error',
},
/**
* Configuring Shared Settings
* settings 只會作用在這個 config object 上
* 但這個 config object 中的所有 rules 都可以使用到這個 settings 的內容
*/
settings: {
react: { version: '18.3' },
},
},
{
/**
* js.configs.recommended 的 config object 只會作用在符合 files pattern 的檔案上
*/
...js.configs.recommended,
files: ['**/src/safe/*.js'],
},
/**
* 如果 import 的是 array of config object,
* 則可以用 array spread operator 把它展開
* */
...exampleConfigs,
];
在 CLI 中帶入參數 --inspect-config 會額外開啟 config inspector,可以用來檢視不同的檔案套用到了哪些 Rules,非常方便。
Legacy (v8 以前)
Command Line Interface
Command Line Interface @ ESLint
# 安裝 eslint cli
$ npm i eslint
# 初始化 eslint 專案
$ npx eslint --init # To check syntax, find problems, and enforce code style
# 執行 eslint
$ eslint [options] [file|dir|glob]*
# 留意: --ext 主要是針對資料夾使用,表示只要 lint 這個資料夾內的特定副檔名,
# 但如果給的是檔案路徑,則 "ext" 這個參數會被忽略,一定會 lint 到這個檔案
$ eslint . --ext .jsx,.js,.ts,.tsx --cache --quiet --report-unused-disable-directives
# 只檢查和 develop branch 相比有變更的檔案(origin/develop...HEAD)
# 且不要檢查被刪除的檔案(--diff-filtered=d)
$ npx eslint -c .eslintrc $(git diff --name-only --diff-filter=d develop...HEAD)
# 檢視並複製當前套用到的 eslint config
$ npx eslint --print-config path::String | pbcopy
使用範例
# eslint [options] file.js [file.js] [dir]
$ eslint 'src/**/*.ts' # 檢驗所有 src 中的 .ts 檔
$ eslint file1.js file2.js
$ eslint lib/**
修復問題
# Fixing problems:
# --fix 自動修復問題
# --fix-dry-run 自動修復問題,但不儲存檔案
$ eslint 'src/**/*.ts' --fix
透過 npm 執行
// package.json
"scripts": {
"lint": "eslint src/**/*.ts"
}
執行:
$ npm run lint -- --fix
設定 ESLint
ESLint Configuration @ ESLint
設定方式
ESLint 有兩種最主要的設定方式:
- 註解:在檔案中直接透過 JavaScript 的註解來進行設定
- 設定檔:為整個專案進行設定,一樣有兩種設定方式
- 使用 JavaScript、JSON 或 YAML 檔案來,它可以是
.eslintrc.*的檔案 - 或在
package.json中使用eslintConfig這個欄位來進行設定
- 使用 JavaScript、JSON 或 YAML 檔案來,它可以是
透過 ESLint CLI 可以快速建立設定檔。
定義規則(rules)
這裡的 semi 和 quotes 是 ESLint 中可以套用的規則(rules),陣列中的:
- 第一個值是「錯誤層級(error level)」:
off或0- 關閉規則warn或1- 將該規則顯示為警告,但仍可執行error或2- 將規則顯示為錯誤,會跳出錯誤後不執行,無法成功編譯
- 第二個值則是針對該規則的「設定」,例如在
semi規則中的always表示總是要有分號;quotes規則中的double則表示要使用雙引號。
// .eslintrc.*
{
"rules": {
"semi": ["error", "always"], // "semi": "error",
"quotes": ["error", "double"],
"no-console": "off"
}
}
如果是針對第三方 plugins 要設定規則的話,最前面會戴上該 plugin 的名稱,例如:
// 針對 jest 這個 plugin 套用規則(要留意 jest 這個 plugin 需要在 "plugins" 或 "extends" 欄位中被啟用(activate)過。
{
"rules": {
"jest/no-disabled-tests": "warn",
"jest/no-focused-tests": "error"
}
}
定義解析選項(parser options)
keywords: parserOptions
設定 parser options 可以幫助 ESLint 決定什麼是解析錯誤,所有語言預設的選項都是 false。
預設的 ESLint 並沒有支援所有最新的 ES6 語法,因此若有需要可以加上 { "parserOptions": { "ecmaVersion": 6 } } 的設定。
相關的設定如下:
-
ecmaVersion- 設成 3, 5 (default), 6, 7, 8, 9, 10 or 11 來指定要使用哪一版本的 ECMAScript 語法,也可以用年份寫2015等同於 6,2016等同於 7,以此類推。 -
sourceType- 設成script(default) 或module(如果你使用的是 ECMAScript modules)。 -
ecmaFeatures- 用來定義希望使用語言中哪些額外的功能globalReturn- 可以在 global scope 下使用returnimpliedStrict- 可以在全域使用 Strict Modejsx- 可以使用 JSX
// .eslintrc.json
{
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"settings": {
// 這裡可以設定 react 的版本
"react": {
"version": "16.13.1"
}
}
}
定義環境(environments)
keywords: env
Specifying Environments @ ESLint
透過定義環境可以讓 ESLint 中知道有哪些可用的環境變數或全域變數(global variable),例如,console.log, alert 等等。其中常見的選項包含 browser, node, commonjs,設定方式如下:
// .eslintrc.json
{
"env": {
"browser": true,
"node": true,
"es2021": true,
"jest": true
}
}
或者在 package.json 設定也可以:
// package.json
{
"name": "my-package",
"version": "0.0.1",
"eslintConfig": {
"env": {
"browser": true,
"node": true
}
}
}
設定全域變數(global environments)
透過 globals 欄位可以哪些變數是可以直接在檔案中使用的全域變數,設定方式如下:
// eslintrc.json
/**
* 設定 var1 和 var2 為全域變數
* writable 表示該變數可以被重新定義該變數
* readonly 則不能重新定義該變數
**/
{
"globals": {
"var1": "writable",
"var2": "readonly"
}
}
設定外掛(plugins)
在 ESLint 中可以使用第三方的套件,其中在使用這些套件前需要先透過 npm 進行安裝。在設定時,每個套件名稱前面的 eslint-plugin- 可以省略不寫:
// eslintrc.json
{
"plugins": ["plugin1", "eslint-plugin-plugin2"]
}
延伸設定檔(Extending Configuration Files)
Extending Configuration Files @ ESLint Configuration
由 extends 延伸後的規則,可以在 rules 欄位中進行修改或覆蓋。
extends 的欄位可以是:
- 透過字串來定義設定檔
- 透過字串陣列(array of strings)來定義,每一個設定都會延伸自前一個設定檔
extends 的設定檔可以是「設定檔的路徑」或「共用的設定檔(shareable config)」,例如
eslint:recommended,eslint:all),同樣的套件名稱前面的eslint-config-可以省略。
// .eslintrc.js
// 透過 extends 擴增的規則可以再透過 rules 進行修改或覆蓋
module.exports = {
extends: 'eslint:recommended',
rules: {
// enable additional rules
indent: ['error', 4],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'double'],
semi: ['error', 'always'],
// override default options for rules from base configurations
'comma-dangle': ['error', 'always'],
'no-cond-assign': ['error', 'always'],
// disable rules from base configurations
'no-console': 'off',
},
};
overrides
How does overrides work @ ESLint
overrides 則可以把規則套用在特定的檔案上。例如,下面的設定檔為例,會把規則套用在所有符合 .ts 和 .tsx 的檔案:
// .eslintrc.js
module.exports = {
overrides: [
{
files: ['**/*.ts', '**/*.tsx'],
// 各種規則...
},
],
};
建立自己的 config
How to Create Your Own ESLint Config Package @ freecodecamp
程式碼中備註
整支檔案隱藏警告
keywords: eslint-disable, eslint {rule}: 0
忽略所有規則
放在檔案開頭:
/* eslint-disable */ // 在該檔案關閉 ESLint
忽略特定規則
// 放在檔案的最上方
/* eslint-disable [rule-name] */
/* eslint-disable no-alert, no-console
off or 0 - 關閉規則
warn or 1 - turn the rule on as a warning (doesn’t affect exit code)
error or 2 - turn the rule on as an error (exit code is 1 when triggered)
/* eslint no-unused-vars: 0 */
/* eslint no-unused-vars: "error" */
/* global myVar1, myVar2 */ // 忽略未定義的全域變數
於 package.json 中設定
忽略特定的全域變數也可以在 package.json 中加上:
{
"standard": {
"globals": ["myVar1", "myVar2"]
}
}
特定行數隱藏警告
keywords: eslint-disable-line, eslint-disable-next-line, eslint-disable-line {rule}, eslint-disable-next-line {rule}
忽略單行
忽略所有規則
file = 'I know what I am doing'; // eslint-disable-line
// eslint-disable-next-line
alert('foo');
忽略特定規則
alert('foo'); // eslint-disable-line no-alert, quotes, semi
// eslint-disable-next-line no-alert
alert('foo');
忽略多行
keywords: eslint-disable, eslint-enable
忽略所有規則
/* eslint-disable */
alert('foo');
/* eslint-enable */
忽略特定規則
/* eslint-disable no-alert, no-console */
alert('foo');
console.log('bar');
/* eslint-enable no-alert, no-console */
TypeScript
在 JS 的專案中使用 TS
當專案中 JS 檔和 TS 檔並存時,可以使用 ESLint 提供的 overrides 方法,保持原本對 JS lint 的規則,針對 TS 檔再套用其他規則:
module.exports = {
/* 原本針對 JS 寫的 eslint 設定... */
// overrides 中填寫針對 TS 的 ESLint 設定
overrides: [
{
files: ['./**/*.ts', './**/*.tsx'],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'simple-import-sort'],
extends: [
/* ... */
],
rules: {
/* ... */
},
},
],
};
@typescript-eslint
TypeScript ESLint 的官方文件寫的非常清楚,code block 的部分可以點擊「Open In Playground」,就可以檢視對應的 Rules 要怎麼設定。
必看:
TL;DR
- TypeScript 是使用
tsc來編譯 TypeScript 檔案,會吃到的設定檔是tsconfig.json。當在 VSCode 中看到 ts 的錯誤時,就是由 tsc 產生。 tsconfig.eslint.json是給 @typescript-eslint 吃的 tsconfig 檔,它會繼承tsconfig.json。當在 VSCode 中出現 @typescript-eslint 的錯誤就是由它產生的。- 出現
Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.的錯誤時,表示 ESLint 想要解析的檔案並沒有被列在給 @typescript-eslint 所涵括到的檔案中。
所有規則
- rules @ typescript-eslint-plugin
有些 ESLint 內建的規則需要先被關掉
I am using a rule from ESLint core, and it doesn't work correctly with TypeScript code @ TypeScript ESLint Q & A
// .eslintrc
{
"rules": {
// note you must disable the base rule as it can report incorrect errors
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": [
"error",
{ "functions": false, "classes": true, "variables": true, "typedefs": true }
]
}
}
@typescript-eslint/ban-types
- ban-types @ Github
- allow selective disable of default options with
falsevalue @ GitHub PR
如果只想要關掉對於 {} 的警告:
// .eslintrc
// https://github.com/typescript-eslint/typescript-eslint/pull/2137
{
"types": {
"{}": false
},
"extendDefaults": true
}
Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser
錯誤描述:
error Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: .eslintrc.js.
The file must be included in at least one of the projects provided

Parsing error: ESLint was configured to run on `<tsconfigRootDir>/vite.main.config.ts` using `parserOptions.project`: /users/.../tsconfig.json
However, that TSConfig does not include this file. Either:
- Change ESLint's list of included files to not include this file
- Change that TSConfig to include this file
- Create a new TSConfig that includes this file and include it in your parserOptions.project
See the typescript-eslint docs for more info: https://typescript-eslint.io/linting/troubleshooting#i-get-errors-telling-me-eslint-was-configured-to-run--however-that-tsconfig-does-not--none-of-those-tsconfigs-include-this-file

問題原因:
當開啟 'plugin:@typescript-eslint/recommended-requiring-type-checking' 時,@typescript-eslint 會使用 tsconfig 的設定,並對型別做出檢查。這時候tsconfig 會編譯到的檔案與 .eslintrc.js 中會處理到的檔案不同,例如 tsconfig 只會處理 /src 內的檔案,但 .eslintrc.js 則是會處理所有專案中的 js 檔。
解決方式:
-
如果你「不要」 lint 這個檔案,則使用
.eslintignore或 ESLint 中的ignorePatterns來忽略掉這隻檔案 -
如果你「要」 lint 這個檔案:
-
但「不要」這個檔案出現和型別有關的錯誤(type-aware linting):
- 最簡單方式就是使用 ESLint
overrides的設定,只針對特定的檔案啟用這個規則:
// .eslintrc.cjsmodule.exports = {// ... the rest of your config ...overrides: [{// specify the files that should be has type-aware linting:files: ['./src/**/*.{ts,tsx}'],parserOptions: {project: true,tsconfigRootDir: __dirname,},extends: ['plugin:@typescript-eslint/recommended-requiring-type-checking'],},],};@typescript-eslint在 v6 之後可能會有更簡單的設定方式。
- 最簡單方式就是使用 ESLint
-
同時「要」這個檔案有出現和型別有關的錯誤(type-aware linting)
-
確定這個檔案有被列在 tsconfig 中的
include內// tsconfig.json{// ..."include": ["src",// 確定 ESLint 要執行的檔案,有被包含在 tsconfig 的 include 中"vite.*.config.ts"]} -
如果這個檔案想要被 lint 但並不歸在 tsconfig 要處理的範疇中(例如,
tests/, 或.eslintrc.js等等),則建立另一個tsconfig.eslint.json的檔案,將這個檔案放在include中,參考這個tsconfig.eslint.json和.eslintrc.js。(之所以這樣能解決,是因為 tsc 預設會吃tsconfig.json,在沒有填include規則的情況下,預設會是["**/*"]也就是專案中的所有檔案,因此就不會有想要 lint 但卻沒有被 tsc 包含到的情況。但實際上,我們並不是真的要 lint 所有檔案,這時候針對要 lint 的檔案在用tsconfig.eslint.json來做限制)。
-
-
搭配 husky 和 lint-staged
如果每次 git commit 前沒有先針對程式碼進行 ESLint 的檢查,這樣 linter 的功能等於只做了一半,因為開發者有可能完全不管 ESLint 的錯誤,還是把不符合 eslint 規範的程式碼推到 github 上。
husky
為了避免這個問題,我們可以使用 husky 這套工具,在建立 commit 時進行 ESLInt 的檢查。
# 第一次安裝 husky 才需要執行
$ npx husky-init && npm install
接著打開 .husky/pre-commit 這隻檔案,預設的情況下 husky 會在 git pre-commit 的階段執行 npm test,我們可以加上 eslint 的指令:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx eslint . --ext .js,.ts.,.jsx,.tsx
npm test -- --watchAll=false
如此,husky 就會在 git 的 pre-commit hook 階段執行 eslint。
lint-staged
但如果每次建立 git commit 時都要對所有的檔案執行 eslint 的檢查的話非常沒有效率,有沒有可能只針對在 git staged 中的檔案執行 eslint 的檢查呢?