靜態分析

「靜態分析」是一種測試,可以在無須實際執行程式碼或編寫自動測試的情況下,自動檢查程式碼。如果您使用 VSCode 等 IDE,可能已經看到這類測試,而 TypeScript 執行的類型檢查是一種靜態分析,可在錯誤或警告下方顯示為波形。

ESLint

ESLint 這項工具可針對程式碼集的潛在問題提供意見回饋。這些問題可能類型為「安全」,但其本身俱有錯誤或非標準行為。ESLint 可讓您套用在程式碼集上檢查的多項規則,包括其中多項規則的「建議」組合。

ESLint 規則的良好範例就是 no-unsafe-finally 規則。如此一來,您就不能在 finally 區塊內編寫用來修改程式控制流程的陳述式。這是一項很棒的規則,因為這是撰寫不易遵循的 JavaScript 程式碼方法。但良好的程式碼審查程序也應能偵測。

  try {
    const result = await complexFetchFromNetwork();
    if (!result.ok) {
      throw new Error("failed to fetch");
    }
  } finally {
    // warning - this will 'overrule' the previous exception!
    return false;
  }

因此,ESLint 並不能取代健全的審查程序 (以及定義程式碼集的樣式指南),因為我們並未擷取開發人員可能會嘗試導入程式碼集的所有 unorthodox 方法。歡迎參閱 Google 工程做法指南的簡短章節,瞭解如何簡化文件。

ESLint 可讓您破壞規則,並將程式碼標示為「允許」。舉例來說,如要允許先前的邏輯,您可以加上註解,如下所示:

  finally {
    // eslint-disable-next-line no-unsafe-finally
    return false;
  }

如果您發現自己經常打破規則,請考慮將其關閉。這些工具鼓勵以特定方式編寫程式碼,但您的團隊可能已有人以其他方式編寫程式碼,並且已經瞭解這種方法的風險。

最後,在大型程式碼集上啟用靜態分析工具,可能會因為用其他方法運作的程式碼,產生許多沒有幫助的雜訊 (且難以重構)。因此,在專案的生命週期中提早啟用會比較容易。

支援瀏覽器的 ESLint 外掛程式

您可以在 ESLint 中新增外掛程式,標記使用未廣泛支援的 API,或是目標瀏覽器清單不支援的 API。eslint-plugin-compat 套件會在使用者可能無法使用 API 時向您發出警告,因此您不必持續追蹤 API。

靜態分析的類型檢查

學習 JavaScript 時,新手開發人員通常會瞭解這是「弱型」語言。也就是說,您可以將變數宣告為單一類型,然後再使用相同的位置處理完全不同的變數。這與 Python 和其他指令碼語言類似,但與 C/C++ 和 Rust 等編譯語言不同。

這種語言可能很適合入門,我們說這讓 JavaScript 變得越來越容易使用,但這通常是某些程式碼集失敗,或至少會造成混淆錯誤。舉例來說,如果傳遞 number 且預期存在 string 或物件類型的位置,則錯誤類型的值可以傳播到各種程式庫之前,最後造成 TypeError 混淆。

TypeScript

在 JavaScript 缺少輸入資訊的情況下,TypeScript 是最主要的解決方案。本課程會廣泛地使用。儘管這不是 TypeScript 課程,但它可以提供靜態分析,因此成為工具箱中重要的一環。

以簡短示例為例,這段程式碼預計會收到接受 string 名稱和 number 年齡的回呼:

const callback = (name: string, age: string): void => {
  console.info(name, 'is now', age, 'years old!');
};
onBirthday(callback);

透過 TypeScript 執行,或在 IDE 懸停在 IDE 上方時產生下列錯誤:

bad.ts:4:12 - error TS2345: Argument of type '(name: string, age: string) => void' is not assignable to parameter of type '(name: string, age: number) => void'.
  Types of parameters 'age' and 'age' are incompatible.
    Type 'number' is not assignable to type 'string'.

4 onBirthday(callback);
             ~~~~~~~~

Found 1 error in bad.ts:4
上一個範例的程式碼顯示在 IDE 中,並在彈出式視窗中顯示錯誤訊息。
VSCode 表示您傳遞的類型不正確。

最終,使用 TypeScript 的目標是避免這類錯誤:年齡應為 number,而非 string,這樣會導致專案發生問題。使用其他類型的測試,這種錯誤可能難以偵測。此外,類型系統可以在測試撰寫前提供意見回饋。如此一來,開發人員就能在開發軟體時 (而不是最終執行程式碼) 及早提供類型錯誤的意見回饋,簡化程式碼編寫程序。

使用 TypeScript 時最難的部分就是正確設定。每個專案都需要 tsconfig.json 檔案,該檔案雖然主要由 tsc 指令列工具本身使用,但 IDE (例如 VSCode) 以及許多其他建構工具和工具 (包括 Vitest) 也會讀取檔案。這個檔案包含數百個選項和標記,您可以在這裡找到設定該檔案的實用資源:

TypeScript 一般提示

透過 tsconfig.json 檔案設定及使用 TypeScript 時,請注意下列事項:

  • 確認來源檔案確實已納入並勾選。如果檔案神秘地「沒有錯誤」,可能是因為系統尚未檢查檔案。
  • .d.ts 檔案中明確描述類型和介面,而非在編寫函式時以隱含方式加以說明,因此會更容易測試程式碼集。如果相關介面清晰,要撰寫模擬和「假」版本的程式碼會比較容易。.

TypeScript 不使用任何

noImplicitAny 旗標是最強大且獎勵的設定選項之一。不過,啟用頻率通常最困難,尤其是在已有大型程式碼集的情況下。(根據預設,系統會在 strict 模式下啟用 noImplicitAny 標記,否則不會啟用)。

這個標記會使這個函式傳回錯誤:

export function fibonacci(n) {
  if (n <= 1) {
    return 0;
  } else if (n === 2) {
    return 1;
  }
  return fibonacci(n - 1) + fibonacci(n - 2);
}

雖然作為讀取器,很顯然 n 應為數字,TypeScript 無法確定這是一個數字。如果您使用的是 VSCode,將滑鼠遊標懸停在函式上即可看到下列說明:

function fibonacci(n: any): any

這個函式的呼叫者將能夠傳遞 any 類型的值 (允許任何其他類型的類型),而不只是 number。啟用 noImplicitAny 標記後,您就能在開發期間保護這類程式碼,不必為程式碼撰寫大量的商業邏輯測試,並在特定位置傳遞錯誤的資料類型。

這裡的簡單修正方式是,將 n 引數和 fibonacci 的傳回類型標示為 number

noImplicitAny 標記不會阻礙您明確在程式碼集中寫入 any。您仍可編寫可接受或傳回 any 類型的函式。只會確保您為各個變數提供類型。