前端框架Svelte放棄TS,如何使用純JS實現類型檢查?
近日,前端框架 Svelte 的創建者 Rich Harris 提出要將 Svelte 從 TypeScript 切換到使用 JSDoc 的 JavaScript。這種轉變得到了 Svelte 團隊的大力支持,他們決定在 Svelte 4 代碼庫中從 TypeScript 遷移到 JavaScript JSDoc。而這個決定引起了開發社區的驚訝和懷疑。
那為什么要從 TypeScript 轉向 JavaScript JSDoc 呢?這是否是技術的倒退?JSDoc 又是什么?它有什么特點?如何使用?下面將詳細介紹!
Svelte 是一個現代的 JavaScript 框架,它允許開發者以聲明式的方式寫組件,并在構建時將這些組件轉化為高效、優化的純 JavaScript 代碼。相比于其他框架,Svelte 更加輕巧,在性能和體驗方面也有著不俗的表現。使用 Svelte 可以幫助開發人員更快速地構建交互式應用程序,同時還可以減少運行時性能負擔和包大小。
為什么轉向JSDoc?
Svelte 團隊認為,盡管類型系統非常棒,但作為一種語言,TypeScript有些“麻煩”。主要問題在于使用 TypeScript 會帶來額外的工具。例如,如果在 TypeScript 中構建一個庫,并在另一個項目中使用該庫,就不能只修改代碼庫還需要重新構建代碼,這增加了不必要的復雜性。
為了規避這些問題,Svelte 團隊決定使用 JavaScript 和 JSDoc 注釋來實現類型安全。這種方法提供了所有類型安全的好處,而沒有與 TypeScript 相關的缺點。SvelteKit 代碼庫已經采用了這種方法,團隊計劃對 Svelte 4 進行同樣的處理。不過,作為Svelte的用戶,這不會影響在Svelte 中使用 TypeScript 的能力,從Svelte導出的函數仍將具有習以為常的所有 TypeScript 優點(類型檢查、智能感知、內部文檔等)。
什么是 JSDoc?
很多開發人員之所以選擇 TypeScript,是因為強類型可以減少錯誤,并通過代碼完成和彈出幫助等功能改善代碼編輯器中的開發體驗。而主要是 API 文檔工具的 JSDoc 也可以用于類型檢查。
JSDoc 是一種用于在 JavaScript 代碼中編寫文檔和類型注釋的標記語言,它使用類似于JavaDoc 的注釋語法。通過在代碼中添加特定的注釋標記,可以生成文檔,提高代碼的可讀性和可維護性。JSDoc不僅可以描述函數的參數和返回值類型,還可以用來描述類、對象、模塊和命名空間等各種 JavaScript 實體的屬性和方法。
那相較于 TypeScript,JSDoc 有什么優點呢?
- 與語言無關:JSDoc只是一種在類似于JavaScript的語言中編寫文檔和類型注釋的方式,使其更加靈活??梢栽诟鞣N環境中使用它,而TypeScript可能不太適合某些環境。
- 易于集成:由于 JSDoc 只是基于注釋的系統,因此不需要更改代碼或工具。可以開始向現有的JavaScript代碼庫添加JSDoc注釋,而無需太多麻煩。
- 學習曲線較低:與TypeScript相比,JSDoc非常直接明了,學習起來更容易,TypeScript可能需要開發人員學習新的語法和類型概念。
- 文檔受益:JSDoc為編寫代碼文檔提供了一種一致的方法。這使得其他開發人員更容易理解代碼庫,并有助于生成文檔。
- 漸進式采用:可以逐漸向代碼庫添加JSDoc,這樣可以逐步將類型檢查和文檔引入項目,而無需完全采用TypeScript。
- 無需構建步驟:JSDoc不像TypeScript那樣需要構建步驟進行類型檢查和轉譯。
如何使用 JSDoc?
使用 JSDoc 不需要任何前置操作。只需要在 JavaScript 代碼中添加 JSDoc 注釋即可。JSDoc 注釋以“/**”開頭,以“*/”結尾,位于要描述的代碼塊之前。可以通過以下方式來將 JSDoc 用于類型檢查。
- 在每個變量聲明、函數聲明等之前添加 JSDoc 注釋,描述它們的類型和用途。例如:
/**
* @type {number}
*/
const num = 42;
/**
* 兩數之和
* @param {number} x
* @param {number} y
* @returns {number} 返回值
*/
function add(x, y) {
return x + y;
}
- 使用 JSDoc 注釋來描述自定義類型和接口。例如:
/**
* @typedef {Object} Person
* @property {string} name - The person's name.
* @property {number} age - The person's age in years.
*/
/**
* @interface Shape
* @property {number} x
* @property {number} y
* @property {number} width
* @property {number} height
*/
- 可以使用文檔生成工具(如 JSDoc-to-HTML)將 JSDoc 注釋自動生成為文檔。例如,在使用 JSDoc 注釋編寫完整的庫或應用后,可以使用 JSDoc-to-HTML 工具將其轉換為漂亮的文檔。
JSDoc 以@標記名稱的形式提供了很多標記,常用的包括:
- @param:用于描述函數的參數。允許指定參數名稱、類型和描述信息。
- @returns:用于描述函數返回值的類型和描述信息。
- @typedef:用于定義自定義類型或對象。允許指定類型名稱、屬性列表和描述信息。
- @property:用于描述對象的屬性。允許指定屬性名稱、類型和描述信息。
- @callback:用于描述回調函數的參數和返回值類型。
- @class:用于描述一個類。允許指定類的名稱、屬性、方法和描述信息。
- @constructor:用于描述一個構造函數。允許指定構造函數的參數、返回值和描述信息。
- @enum:用于定義一個枚舉類型。允許指定枚舉名稱、屬性列表和描述信息。
- @namespace:用于描述命名空間。允許指定命名空間的名稱和描述信息。
- @readonly:用于指定只讀屬性或參數。
- @private:用于指定私有屬性或方法。
- @public:用于指定公共屬性或方法。
- @protected:用于指定受保護的屬性或方法。
- @throws:用于描述函數可能引發的異常。允許指定異常類型和描述信息。
這些標記只是 JSDoc 提供的許多標記中的一部分。JSDoc 還提供了許多其他標記,如 @augments、@example、@ignore、@link、@since 等。通過使用這些標記,可以更好地記錄和描述 JavaScript 代碼。
需要注意,盡管可以使用 JSDoc 代替 TypeScript 進行類型檢查,但它并不像 TypeScript 一樣強制執行類型檢查。如果在 JSDoc 注釋中錯誤地描述了類型,或者沒有提供足夠的類型信息,將無法得到類型檢查的保護,這可能會導致運行時錯誤。因此,在使用 JSDoc 進行類型檢查時,需要格外小心,并盡可能詳細地記錄變量和參數的類型。
小結
最終 JSDoc 會取代 TypeScript 進行類型檢查嗎?我認為是不會的。TypeScript 非常適合應用開發,而且它正在不斷改進。不過對于庫開發來說,使用純 JavaScript 和 JSDoc 注釋似乎是更好的選擇。
絕大多數開發人員不是在構建庫,而是在構建應用。因此,TypeScript 將保持主要的類型檢查方式,直到 JavaScript 實現原生類型檢查為止。
選擇 TypeScript 還是帶有 JSDoc 的 JavaScript 取決于開發團隊或開發人員的需求和偏好。對于庫作者來說,JavaScript 和 JSDoc 的簡單性和靈活性特別有吸引力的。對于已經具有構建中的應用,TypeScript 仍然可能是首選。