繁體中文(台灣)
  • typescript
  • javascript
  • nodejs
  • node_modules
  • module-augmentation

TypeScript 模組增強與處理巢狀 JavaScript 檔案

學習 TypeScript 中模組增強的基礎,以及如何為巢狀的 JavaScript 檔案添加型別定義。

Gao
Gao
Founder

TypeScript 在過去十多年中成為 JavaScript 生態系統中的重要補充,因為它能夠為 JavaScript 程式碼提供型別安全而日益受到歡迎。

JavaScript 套件的型別

為了向後相容性和靈活性,TypeScript 允許套件作者為他們的 JavaScript 套件提供型別定義。這些型別定義通常儲存在 "DefinitelyTyped" 儲存庫中。你可以使用 @types 範圍來安裝這些型別定義,例如,@types/react 是 React 套件的型別定義。

安裝這些型別定義後,你可以在型別安全的情況下使用該套件。以下是一個使用型別安全定義 React 元件的範例:

模組增強

雖然大多數受歡迎的 JavaScript 套件在 @types 範圍內都有現成的型別定義,但有些套件可能缺少型別定義或型別定義已過期。在此類情況下,TypeScript 提供了一項強大的功能,稱為 "模組增強" 來為這些套件添加型別定義。讓我們看一個範例:

現在,你可以在程式碼中使用這個增強的型別定義:

模組增強不僅可以讓你為套件添加型別定義,還可以擴展現有的型別定義。例如,你可以為 window 物件添加一個新屬性:

並在你的程式碼中使用它:

上一篇文章 中,我們談到了 React Router 函式庫中的一個型別問題,我們必須通過自定義聲明檔來擴展和增強現有型別以克服其影響。

記住使用模組增強時,必須仔細檢查 JavaScript 原始碼以確保型別定義的準確性。不正確的型別定義可能會導致執行階段錯誤。在上面的例子中,window.foo 屬性必須是一個存在於 window 物件上的字串。

全域增強

有時你可能會遇到引入全域變數的指令碼,並且你可能希望為這些全域變數提供型別定義以便在 TypeScript 程式碼中使用它們。例如,如果你有一個設定了名為 __DEV__ 的全域變數的指令碼:

你可以為這個全域變數添加型別定義,如下所示:

現在你可以在你的 TypeScript 程式碼中使用它:

通過組合模組增強和全域增強,你甚至可以擴展 JavaScript 原型的型別定義。然而,這通常不建議,因為它可能會污染全域範圍。

模組增強的強大功能允許這樣的擴展,但要謹慎行事以防止全域範圍污染。

巢狀 JavaScript 檔案

在前面提到的例子中,我們假設可以通過套件的入口檔案來解析 import。但有些套件會匯出沒有對應型別定義的巢狀 JavaScript 檔案。考慮一個名為 foo 的套件,其結構如下:

foo 套件匯出 index.js 檔案作為入口點,還匯出了 bar 目錄。

foo 套件增強型別定義,你可以創建一個 foo.d.ts 檔案:

然而,如果你嘗試在 TypeScript 中 import baz.js 檔案,你會遇到錯誤:

要為 baz.js 檔案增強型別定義,你需要創建一個單獨的 baz.d.ts 檔案:

這確保了 TypeScript 可以定位到模組及其關聯的型別定義:

為了保持有組織的型別定義,你可以在型別定義檔案中模仿套件的結構:

這種方法即使在處理巢狀 JavaScript 檔案時,也能保持你的 TypeScript 程式碼結構化和型別安全。