繁體中文(香港)
  • 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 文件

在前面的例子中,我們假設導入可以通過套件的入口文件解決。然而,某些套件會導出嵌套的 JavaScript 文件,而沒有對應的類型定義。考慮一個名叫 foo 的套件,其結構如下:

foo 套件以 index.js 文件作為入口點,並且還導出 bar 目錄。

要擴展 foo 套件的類型定義,你可以創建一個 foo.d.ts 文件:

然而,如果你嘗試在 TypeScript 中導入 baz.js 文件,你會遇到錯誤:

要擴展 baz.js 文件的類型定義,你需要創建一個單獨的 baz.d.ts 文件:

這確保 TypeScript 可以定位模塊及其相關的類型定義:

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

這種方法使你的 TypeScript 代碼保持結構化和類型安全,即使在處理嵌套的 JavaScript 文件時也是如此。