@ts-check 當即上手,JSDoc 添加類型

因爲 JavsScript 是弱類型,因此在大型項目中使用時顯得能力略有不足。從七月份在騰訊實習到如今,接觸到了很多項目的代碼,平均算來天天都有 70% 的時間用於閱讀、理解他人的代碼。每次閱讀他人代碼的時候,我心中都會冒出來兩個強烈的願望:要是 JavaScript是強類型的多好!要是文檔能再詳細一點就行了!多虧了 TypeScript 和 JSDoc,這兩個願望都有變成現實的可能。javascript

@ts-check 當即上手

使用 TypeScript 的最佳方式確定是直接使用它的語法來編寫 .ts 文件,而後經過編譯器轉換成 .js 文件。然而對於老項目而言,切換構建每每意味着麻煩和巨大的風險,並且假如未來 JavaScript 也引入了類型系統(這很是有可能),那又得從 TypeScript 切回 JavaScript (迴歸標準)。那麼有沒有一種無痛的方式,讓咱們既能夠享受 TypeScript 帶來的好處,又能不改變項目的現有構建方式呢?java

答案就是 // @ts-check,在 .js 文件的頭部引入這樣一行註釋,就能夠使用 TypeScript 了。git

舉個例子,在下圖中咱們首先聲明瞭一個變量 a,而後把數字 1 賦給了它,接着又把字符串 '123' 賦給了它,看起來好像沒有什麼問題。github

未使用 @ts-check
未使用 @ts-check

如今讓咱們加上// @ts-check,咦,怎麼 a 下面出現了紅色的報錯?把鼠標移到 a 處,發現報錯是"Type '"123'" is not assignable to type 'number'",也就是說在 TypeScript 中這種把字符串 '123' 賦值給數字變量 a 的作法是不妥的。segmentfault

使用 @ts-check
使用 @ts-check

享受 TypeScript 類型系統的好處就是這麼簡單,不須要改變構建,不須要進行項目的遷移,所須要作的僅僅是在 .js 文件的頭部加入 // @ts-check(前提是你使用的是 VS Code,不過其它的編輯器下載相應的插件便可)。數組

JSDoc 添加類型

若是僅僅使用 // @ts-check的話,咱們只能使用它的自動類型推斷功能,這對於大型項目來講是遠遠不夠的,咱們但願能像強類型語言同樣指定每一個變量的類型。本着不對項目產生侵入的原則,TypeScript 能夠經過 JSDoc 風格的註釋來完成這一點。接下來的舉例說明取自官方的文檔編輯器

/** * 使用 "@type" 來聲明類型 * @type {string} */
let var1;

/** @type {Window} */
let var2;

/** * 用 「return」 說明函數的返回值類型 * @return {number} */
function fn1() {}

/** * 能夠像使用 "@return" 同樣使用 "@returns" * @returns {{a: string, b: number}} */
function fn2() {}

/** * 能夠指定 union 類型,如字符串或者布爾值 * @type {(string | boolean)} */
let var3;

/** * 聲明元素類型是數字的數組 - 方式1 * @type {number[]} */
let var4;

/** * 聲明元素類型是數字的數組 - 方式2 * @type {Array.<number>} */
let var5;

/** * 聲明元素類型是數字的數組 - 方式3 * @type {Array<number>} */
let var6;

/** * 聲明對象類型 * @type {{a: string, b: number}} */
let var7;

/** * 用 "@typedef" 自定義複雜類型 * @typedef {Object} SpecialType - 建立一個新的類型 'SpecialType' * @property {string} prop1 - SpecialType 屬性 prop1 是 string 類型 * @property {number} prop2 - SpecialType 屬性 prop2 是 number 類型 * @property {number=} prop3 - SpecialType 屬性 prop3 是可選的 number 類型 * @prop {number} [prop4] - SpecialType 屬性 prop4 是可選的 number 類型 * @prop {number} [prop5=42] - SpecialType 屬性 prop5 是可選的 number 類型(默認值 42)) */
/** @type {SpecialType} */
let specialTypeObject;


/** * 聲明函數參數類型 * @param p0 {string} - TS 風格聲明 p0 * @param {string} p1 - p1 是 string 類型參數 * @param {string=} p2 - p2 是可選的 string 類型參數 * @param {string} [p3] - 另一種可選參數寫法 * @param {string} [p4="test"] - p4 是可選的 string 類型參數(默認值爲 "test") * @return {string} - 函數返回值是 string 類型 */
function fn3(p0, p1, p2, p3, p4){
  // TODO
}

/** * 也能夠使用模板來聲明類型 * 如 fn4 表示返回值和參數 p1 是相同類型 * @template T * @param {T} p1 * @return {T} */
function fn4(p1){}複製代碼

寫在最後

對於老項目,使用 // @ts-check 和 JSDoc 引入 TypeScript 來享受類型系統的好處是最簡單、學習成本最低的方法。對於新項目,相較於激進地使用 .ts 文件,我認爲 // @ts-check 和 JSDoc 是更好的方法,由於 JavaScript 在不久的將來頗有可能會引入可選的類型系統(相似於Python 3),到時候能夠避免再從 TypeScript 迴歸 JavaScript。函數

參考連接

  1. Type Checking JavaScript Files
  2. JSDoc support in JavaScript

本文首發於elvin 的博客學習

相關文章
相關標籤/搜索