跳到主要內容

常見問題集

我正在使用 ESLint 核心規則,但它無法正確處理 TypeScript 程式碼

這是因為 TypeScript 新增了 ESLint 尚未認知的新功能。

第一步是 查看我們的「擴充功能」規則清單。擴充功能規則是以擴充基本 ESLint 規則的方式,來支援 TypeScript 語句。如果您有找到您要的規則,可以先試試看是否適用於您的情況。您可以停用基本規則並啟用擴充功能規則來設定它。以下是使用 semi 規則的範例:

{
"rules": {
"semi": "off",
"@typescript-eslint/semi": "error"
}
}

如果您找不到現有的擴充規則,或擴充規則不適用於您的情況,那麼您可以繼續檢查我們的問題。 貢獻指南說明了提出問題的最佳方式

我們每週發布一個新的版本工具。 確保您 查看我們的最新「擴充」規則清單 提交問題之前

當我收到「我們已知如果預設專案有許多檔案執行,將會導致效能問題,並降低檢查速度」的錯誤訊息時。

使用 EXPERIMENTAL_useProjectService allowDefaultProjectForFiles 並搭配過於廣泛的 glob 所導致的錯誤。 allowDefaultProjectForFiles 為每個包含的「專案外」檔案建置一個新的 TypeScript「程式」,而且每個檔案會產生效能的耗損。

要解決此錯誤,請縮小用於 allowDefaultProjectForFiles 的 glob,以減少檔案。例如

eslint.config.js
parserOptions: {
EXPERIMENTAL_useProjectService: {
allowDefaultProjectForFiles: [
- "**/*.js",
+ "./*.js"
]
}
}

您可能還需要在 tsconfig.json 中包含更多檔案。例如

tsconfig.json
"include": [
"src",
+ "*.js"
]

如果您無法做到,請 在 typescript-eslint 的 typescript-estree 套件中提交問題,說明您的使用案例,以及為何您需要更多專案外的檔案檢查。務必附上我們可以處理的最小重現範例,以了解您的使用案例!

當我收到「已設定 ESLint 來執行 ... 不過,TSConfig 中沒有包含這個檔案,或任何 TSConfig 中都未包含這個檔案」的錯誤訊息時

此錯誤是由於 ESLint 設定檔會要求為 TypeScript 設定中未包含的檔案產生型別資訊。

修復錯誤

  • 如果您要檢查檔案
  • 如果你對檔案執行 linting
    • 如果你不想對檔案執行具備類型感知的 linting

      eslint.config.js
      import tseslint from 'typescript-eslint';

      export default tseslint.config(
      // ... the rest of your config ...
      {
      files: ['**/*.js'],
      extends: [tseslint.configs.disableTypeChecked],
      },
      );
      • 或者,你可以手動停用檔案的類型檢查,將 parserOptions: { project: false } 設定為想要排除的檔案的替代設定。
    • 如果你對檔案執行具備類型感知的 linting

      • 檢查你提供給 parserOptions.project 中每個 TSConfig 的 include 選項 - 你必須確定所有檔案都與 include 全域比對相符,否則我們的工具將無法找到它。
        • 如果檔案是 .cjs.js.mjs 檔案,請確定 allowJs 已啟用。
      • 如果你的檔案不應該成為現有 tsconfig 中的一部分(例如,它是儲存庫本地的腳本/工具),請考慮在專案根目錄建立一個新的 tsconfig(我們建議把它命名為 tsconfig.eslint.json)並在它的 include 中列出這個檔案。你可以查看我們之前在這個儲存庫中使用的設定檔作為範例

更多詳細資訊

這個錯誤可能是因為以下兩件事同時發生

  • 原始檔案的 ESLint 設定檔在 parserOptions.project 中至少指定一個 TSConfig 檔案。
  • 那些 TSConfig 檔案中沒有包含要執行的來源檔案。

當指定 TSConfig 檔案來剖析來源檔案時,@typescript-eslint/parser 會使用第一個能夠包含該來源檔案的 TSConfig(依據 aka.ms/tsconfig#include)來產生類型資訊。但是,如果沒有指定的 TSConfig 包含來源檔案,剖析器將無法產生類型資訊。

這個錯誤最常發生在未包含在專案 TSConfig 中的設定檔或類似的檔案。例如,許多專案有下列類型的檔案

  • 一個包含 parserOptions.project: ["./tsconfig.json"].eslintrc.cjs / eslint.config.js
  • 一個包含 include: ["src"]tsconfig.json

在這種情況下,使用包含 ESLint 擴充功能的 IDE 瀏覽檔案時,會顯示檔案未包含在 tsconfig.json 中而無法進行檢查的錯誤提示。

請參閱我們的文件 了解類型感知 linting

會收到「檔案必須至少包含在提供的專案之一中」的錯誤訊息

您使用的 @typescript-eslint/parser 版本已過期。請更新至最新版本,以取得此錯誤訊息更具資訊性的版本,說明如 上方

如何啟用 @typescript-eslint 規則?

首先,請確定您已閱讀文件並了解 ESLint 組態檔案

我們的 規則文件 會詳細說明每個規則在「選項」標題下支援的選項。我們使用 TypeScript 類型來描述規則的 選項元組類型,您可以使用「選項」元組類型來組態規則。在您的組態檔案中,規則物件的鍵值是您要組態的規則名稱,而值會依照以下格式

type Severity = 'off' | 'warn' | 'error';
type RuleConfig =
| Severity
| [Severity]
| [
Severity,
// Options is the tuple type from the rule docs
...Options,
];

範例

eslint.config.js
export default tseslint.config(
// ... the rest of your config ...
{
rules: {
// turns a rule on with no configuration (i.e. uses the default configuration)
'@typescript-eslint/array-type': 'error',
// turns on a rule with configuration
'@typescript-eslint/no-explicit-any': ['warn', { ignoreRestArgs: true }],
},
},
);

typescript-eslint 認為我的變數永遠不為 null / 是 any / 等,但我明顯認為並非如此

我們的類型感知規則幾乎總是信任 TypeScript 編譯器提供的類型資訊。因此,要檢查我們的規則是否運作正常,最簡單的方法就是檢查有問題變數的類型,例如在您的 IDE 中將滑鼠指標移至變數上。

如果 IDE 也顯示類型永遠不為 null / 是 any,您需要修正類型。一個很常見的情況是 no-unnecessary-condition 規則。請以以下程式碼為例

let condition = false;

const f = () => (condition = true);
f();

if (condition) {
//^^^^^^^^^ Unnecessary conditional, value is always falsy.
}

你可以將滑鼠指標懸停在 IDE 中的 condition 上,查看該類型的實際文字類型為 false。在這種情況下,typescript-eslint 不太可能會比 TypeScript 本身更了解,因此你需要透過斷言(例如 let condition = false as boolean)修改類型來修復該報告。

如果 IDE 提供的類型資訊與 typescript-eslint 的報告不同,則確保用於 IDE、typescript-eslint 和 tsc 的 TypeScript 設定相同:相同的 TypeScript 版本、相同的類型檢查編譯器選項,且在專案中包含相同的文件。例如,如果某個類型在其他文件中宣告,但並未包含該文件,則該類型會變成 any,並會使我們的 no-unsafe-* 規則回報問題。

我可以將 ESLint 的 --cache 與 typescript-eslint 搭配使用嗎?

ESLint 的 --cache 選項以檔案為單位進行快取。你可以使用它,但它只會對未輸入類型的規則可靠運作- 即使如此,並非總是如此。

檢查檔案間邏輯的任何 ESLint 規則(包括來自 eslint-plugin-import 的許多規則)都會建立跨檔案依賴關係。已輸入類型的 linting 規則 在實務中幾乎總是會依賴各檔案的類型。ESLint 的快取並未考量這些跨檔案依賴關係。

我們不建議使用 --cache

我使用需要自訂檔名副檔名的架構(例如 Vue),且會收到「你應該將 parserOptions.extraFileExtensions 新增到你的設定檔」之類的錯誤

你可以使用 parserOptions.extraFileExtensions 來指定允許使用的非 TypeScript 副檔名陣列,例如

eslint.config.js
export default tseslint.config(
// ... the rest of your config ...
{
languageOptions: {
parserOptions: {
tsconfigRootDir: import.meta.dirname,
project: ['./tsconfig.json'],
extraFileExtensions: ['.vue'],
},
},
},
);

在解析 .vue 檔案中的 TypeScript 時,我遇到錯誤

如果你在解析 .vue 檔案時遇到問題,原因可能是需要使用像 vue-eslint-parser 這樣的剖析器來解析 .vue 檔案。在此情況下,你可以將 @typescript-eslint/parser 移到 parserOptions 內部,並將 vue-eslint-parser 用作頂層剖析器。

eslint.config.js
import tseslint from 'typescript-eslint';
import vueParser from 'vue-eslint-parser';

export default tseslint.config(
// ... the rest of your config ...
{
languageOptions: {
parser: tseslint.parser,
parser: vueParser,
parserOptions: {
parser: tseslint.parser,
sourceType: 'module',
},
},
},
);

parserOptions.parser 選項也可指定一個物件,以指定多個 parser。有關詳細資訊,請參閱 vue-eslint-parser 使用指南

我的其中一個 linter 規則在純 JavaScript 檔案中無法正常運作

這是預期中的行為,ESLint 規則不會在檔案副檔名中檢查,因為這會在使用非標準副檔名的環境中造成問題 (例如,.vue.md 檔案都可能包含要進行 linting 的 TypeScript 程式碼)。

如果有些純 JavaScript 程式碼不希望套用特定的 linter 規則,則可以使用 ESLint 的 overrides 設定檔 關閉特定規則,甚至根據 glob 模式變更 parser。

是否應該執行 ESLint 於轉譯輸出的 JavaScript 檔案?

否。

來源 TypeScript 檔案擁有輸出 JavaScript 檔案的所有內容,加上類型註解。並不會因為也對輸出的 JavaScript 檔案進行 linting 而得到任何好處。

TypeScript 必須在本地端進行安裝

請確定您已在本地端安裝 TypeScript,也就是使用 npm install typescript,而不是 npm install -g typescript,或使用 yarn add typescript,而不是 yarn global add typescript。如需更多資訊,請參閱 #2041

如何封鎖 <特定語言功能>

ESLint 核心包含 no-restricted-syntax 規則。此一般性規則允許您為您要封鎖的程式碼指定 選擇器,以及客製化的錯誤訊息。

您可以使用 AST 視覺化工具(例如 typescript-eslint playground > 選項 > 左側邊欄中的 AST Explorer,方法是選擇 ESTree)輔助找出您想封鎖的 AST 結構。

例如,您可以使用下列其中一個設定檔封鎖列舉 (或某種變形):

{
"rules": {
"no-restricted-syntax": [
"error",
// ban all enums
{
"selector": "TSEnumDeclaration",
"message": "My reason for not using any enums at all",
},

// ban just const enums
{
"selector": "TSEnumDeclaration[const=true]",
"message": "My reason for not using const enums",
},

// ban just non-const enums
{
"selector": "TSEnumDeclaration:not([const=true])",
"message": "My reason for not using non-const enums",
},
],
},
}

為什麼在 ESLint 輸出中看不到 TypeScript 錯誤?

TypeScript 編譯器(或您的建置鏈)是特定設計和建置的,用於驗證程式碼庫的正確性。我們的工具不會複製 TypeScript 提供的錯誤,因為這樣會減慢 linting 的執行 [1],並且會重複 TypeScript 已為您輸出的錯誤。

相反地,我們的工具的存在是為了擴充 TypeScript 內建的檢查,使用 linting 規則以超出僅驗證程式碼執行時間正確性的新方式使用類型資訊。

[1] - TypeScript 延遲計算類型資訊,因此要求編譯器產生我們要的錯誤會額外花費大約每個檔案 100 毫秒。這看起來不多,但是根據您的程式碼庫大小,它可以輕易地將 linting 的執行時間增加成數秒到數分鐘之間。

我會收到來自 no-undef 規則的錯誤,它會說全域變數沒有定義,即使沒有 TypeScript 錯誤

no-undef linting 規則未使用 TypeScript 來判斷存在的全域變數 - 相反地,它依賴於 ESLint 的設定檔。

我們強烈建議您不要在 TypeScript 專案中使用 no-undef linting 規則。它提供的檢查已經由 TypeScript 在無需設定檔的情況下提供 - TypeScript 只是做的更好。

在我們的 v4.0.0 版本中,這也適用於類型。如果您從第三方套件(也就是來自 @types 套件的任何東西)使用全域類型,那麼您必須適當地設定 ESLint 來定義這些全域類型。例如:@types/reactJSX namespace 是必須在 ESLint 設定檔中定義的全域第三方類型。

請注意,對於包含 JavaScript 及 TypeScript 的混合專案,no-undef 規則(就像任何規則一樣)可以只針對 TypeScript 檔案關閉,如下所示

eslint.config.js
import tseslint from 'typescript-eslint';

export default tseslint.config(
// ... the rest of your config ...
{
files: ['**/*.{ts,tsx,mts,cts}'],
rules: {
'no-undef': 'off',
},
},
);

如果您選擇保留 ESLint no-undef linting 規則,您可以手動定義 ESLint 設定檔中允許的 globals,或者您可以使用預定義的環境(env)設定檔

如何查看已安裝的版本?

如果你安裝了多個版本的工具,會造成你遇到各種錯誤。因為 ESLint 每次執行時可能會載入不同的版本,取決於你執行的哪個版本 - 導致無法一致的程式碼檢查結果。

在專案根目錄中安裝工具,不代表只會安裝單一版本。你的一個或多個依賴項可能對工具有自己的依賴項,代表 npm/yarn 會另外針對該套件安裝這個版本以便使用。例如,react-scriptscreate-react-app 的一部分)會依賴於我們的工具。

你可以使用以下指令查看專案中已安裝了哪些版本:

npm list @typescript-eslint/eslint-plugin @typescript-eslint/parser

如果你看到安裝了多個版本,你需要使用 Yarn 解析度 來強制使用單一版本,或者將你的根版本降級到與依賴項版本相符。

這種情況下最好的做法是等待你的依賴項發布一個支援我們最新版本的新版本。

如何指定 TypeScript 版本 / parserOptions.typescriptLocation

你無法指定,你也無需指定。

你應該與其他專案一樣使用相同版本的 TypeScript 來進行程式碼檢查。TypeScript 版本在臨界值上常有些微差異,可能導致 typescript-eslint 規則和編輯器資訊之間相互矛盾。例如:

  • @typescript-eslint/strict-boolean-expressions 可能使用 TypeScript 版本 X,並認定變數為 string[] | undefined
  • TypeScript 本身可能位於版本 X+1-beta,並認定變數為 string[]

請參閱 此則議題留言 以了解更詳細的說明。

在我的整合開發環境中,程式碼檢查其他檔案時,並未反映其中一個檔案的變更

tl;dr:重新啟動 ESLint 伺服器以強制更新。

ESLint 目前沒有任何方法在像我們這樣的解析器中,可以得知何時有任何的檔案改變。這表示如果變更會由檔案 A 匯入的檔案 B,不會為檔案 B 更新 lint 快取,即使檔案 B 的文字內容已變更。有時唯一的解決方案是重新啟動你的 ESLint 編輯器擴充功能。

查看 這則留言 來取得更多資訊。

提示

VS Code 的 ESLint 擴充功能 提供 ESLint: 重新啟動 ESLint 伺服器 的動作。

對於跨檔案變更獲得 no-unsafe-* 提醒

查看 當我在我的 IDE 中進行 linting 其他檔案時,對其中一個檔案的變更並未反映出來。規則(例如 no-unsafe-argumentno-unsafe-assignmentno-unsafe-call)經常受到影響。

「'<key>' 屬性已在 '<type>' 節點中被標示為不建議使用。改用 '<key>'。」警告

如果你看到這個警告,可能是因為你正在使用尚未為 TypeScript ESLint v6 更新的 ESLint 外掛程式(或其他工具)。確定你所使用的每個 ESLint 外掛程式(及其他工具)都是最新版本。

如果你使用許多 ESLint 外掛程式,已將每個外掛程式更新到最新版本,且你不確定哪一個外掛程式會造成此抱怨,請嘗試下列其中一個或兩個步驟

  • 使用 --trace-deprecation 執行(例如:npx cross-env NODE_OPTIONS=--trace-deprecation npm run lint
  • 一次停用一半的外掛程式以找出產生問題的外掛程式

再確認這些外掛程式每個都有 GitHub issue 來要求他們釋出支援 TypeScript ESLint v6 的版本。

提示

對於仍然需要支援 typescript-eslint v5 的外掛中更新 ESLint 規則的開發人員:如果新的屬性金鑰不存在,您可能需要 || 回歸到舊的屬性金鑰

- node.typeParameters
+ node.typeArguments || node.typeParameters

欲了解更多脈絡,請參閱 某些屬性名稱為 typeParameters,而不是 typeArguments 議題,以及實作 修復:在需要的地方將 typeParameters 重新命名為 typeArguments 的 pull 要求。

typescript-eslint v6 發布貼文 中有更多關於 typescript-eslint v6 的資訊。

我的 linting 感覺很慢

如果您認為您遇到效能問題,請參閱我們的 效能疑難排解文件

是否支援 TypeScript 專案參考?

是的,但僅限於 EXPERIMENTAL_useProjectService

請參閱 討論專案參考的第 2094 號議題,以瞭解更多詳細資訊。