「靜態分析」是一種測試,可以在無須實際執行程式碼或編寫自動測試的情況下,自動檢查程式碼。如果您使用 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
最終,使用 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
類型的函式。只會確保您為各個變數提供類型。