為什麼用 TypeScript?

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open source. ———— TypeScript 官網

1.第一時間發現類型錯誤

據 rollbar 統計,在前端項目中 10 大錯誤類型如下圖所示:

其中有 7 個是類型錯誤(TypeError):

  • Cannot read property xxx on undefined:無法在 undefined 上讀取 xxx 屬性,通常出現在 a.b.c 的情況。
  • undefined is not an objectundefined 不是對象
  • null is not an object:null 不是對象
  • undefined is not a functionundefined 不是函數,通常出現在 a.b.c() 的情況。
  • Object doesnt support property
  • Cannot read property length:無法讀取 length 屬性,本來期望一個數組,但是變數的實際類型卻不是數組。
  • Cannot set property of undefined:無法給 undefined 設置屬性。

除了 7 個 TypeError,還有一個 ReferenceError:

  • xxx is not defined:xxx 沒有定義。

還有一個 RangeError:

  • 在 JS 中,數組越界並不會拋出 RangeError,但是某些函數則拋出這個錯誤

嘿嘿,看著這些錯誤眼不眼熟?

由於 JavaScript 是一門很靈活的語言,所以以上這些錯誤往往要在代碼運行時才能發現。

2.智能提示

在使用 JavaScript 時,編輯器的智能提示往往很有限,比如提示你最近輸入的變數。

但是基於 TypeScript,由於知道當前變數是什麼類型,所以編輯器能經過類型推導後為你提示這個變數的所有屬性,以及對於函數的參數進行提示和校驗。

此外,對於一般的 JavaScript 項目也可以自己編寫 .d.ts 聲明文件,來獲取類型推導能力。

至於其他的優點在這裡就不展開了...

綜上,在項目中使用 TypeScript 能讓你極大地提高工作效率,並減少大量的類型錯誤。

TypeScript 初體驗

由於目前業務項目中的框架用的是 Vue.js,眾所周知 2.x 版本對於 TypeScript 支持的不是很好,所以就打算先搞個工具函數庫項目試試水。

語言學習

略,這個各種資料很多,這裡就不贅述了...

項目架構

  • 項目入口:src/index.ts,沒有實質內容全是 export * from ...(都是純函數)
  • 實際代碼:根據工具函數分類放在不同的文件中,例如
  • string(字元串相關)
  • env(環境探測)
  • url(鏈接地址)
  • ...
  • 單元測試:test/
  • 文檔目錄:docs/

注意:package.json 中的 sideEffects 欄位要寫成 false,這樣可以方便業務代碼打包時 tree-shaking

相關工具鏈

之前對於 TypeScript 一直在觀望的原因之一就是相關工具鏈的搭配還不是很成熟。不過現在倒是基本明晰了:

  • 1.代碼轉譯 babel([譯] TypeScript 和 Babel:美麗的結合)

TypeScript 和 babel 都可以將你的 ES6+ 代碼轉成 ES5。

但在 Babel v7 之前將兩個獨立的編譯器(TypeScript 和 Babel)鏈接在一起並非易事。編譯流程變為:TS > TS Compiler > JS > Babel > JS (again)

現在只要安裝 @babel/preset-typescript 這個包就能讓你完美結合 babel 和 TypeScript。

  • 2.代碼檢查 eslint(The future of TypeScript on ESLint)

再也不用糾結到底用 tslint 還是 eslint 了,TypeScript 官方已經欽定了 eslint(Migrate the repo to ESLint #30553)。

  • 3.單元測試 jest([RFC] Migrate Jest to TypeScript #7554)

嘿嘿,Facebook 的 jest 和 yarn(Yarns Future - v2 and beyond #6953) 都拋棄自家的 Flow 轉投 TypeScript 的懷抱了

  • 4.代碼打包 rollup(rollup 在 17 年底就使用 TypeScript 重寫了)

雖然 rollup 自己用的是 rollup-plugin-typescript,不過項目中還是選了 rollup-plugin-typescript2

改造過程

  • 安裝各種依賴
  • 配好各種配置文件(eslint、babel、commitlint、jest),其中最重要的是 tsconfig.json
  • 源代碼的文件名後綴由 .js 改成 .ts(單測的文件也改)
  • 然後 TypeScript 的靜態代碼類型檢查就會告訴你有什麼錯誤
  • 看情況改代碼,或者是加 ignore 注釋(有時甚至需要改 tsconfig 的配置)

文檔

文檔標準

TypeScript 官方有一套基於 jsdoc 的文檔標準 tsdoc。

export class Statistics {
/**
* Returns the average of two numbers.
*
* @remarks
* This method is part of the {@link core-library#Statistics | Statistics subsystem}.
*
* @param x - The first input number
* @param y - The second input number
* @returns The arithmetic mean of `x` and `y`
*
* @beta
*/
public static getAverage(x: number, y: number): number {
return (x + y) / 2.0;
}
}

生成文檔

於是順藤摸瓜找到 typedoc 這個自動文檔網站生成器。但這玩意兒的常規操作就是讀取源代碼,然後 duang 地一下,生成一堆頁面。

雖然這樣解決了文檔生成,但是沒法進行開發時實時預覽文檔。

自動生成

0.失敗嘗試:結合 vuepress

由於 typedoc 能導出 md 文件,所以嘗試過將其結合 vuepress。不過由於 typedoc 在生成時會先清空目標目錄下所有文件,折騰起來太麻煩(比如做個插件)。

1.下策:手動觸發文檔生成

沒啥好說的,適用於有毅力的同學。

2.中策:監聽源文件變化,自動觸發文檔生成

雖然能自動生成文檔頁面了,不過預覽時沒法自動刷新頁面。

3.上策:藉助 webpack、gulp、grunt 自動生成文檔並刷新頁面(正好有這三者的 typedoc 插件)

說到開發時自動刷新頁面,第一個自然想到 browser-sync。

  • 雖說 webpack 無所不能,不過殺雞焉用牛刀
  • grunt 這玩意兒有點兒落伍了
  • gulp 正好以前搗鼓過,加這個小需求正好

最後這裡貼一下 gulpfile.js 的代碼,節省一下也有相關需求同學的時間吧。

const gulp = require(gulp)
const typedoc = require(gulp-typedoc)
const browserSync = require(browser-sync).create()

const runTypeDoc = () => gulp
.src([src])
.pipe(typedoc({
out: ./docs,
// 這個文件裏都是 export * from ... 就沒必要導出文檔了
exclude: src/index.ts,
tsconfig: tsconfig.json,
}))

const reload = (done) => {
browserSync.reload()
done()
}

const runBrowserSync = (done) => {
browserSync.init({
server: {
baseDir: ./docs,
},
})
done()
}

const watch = () => gulp.watch(
[README.md, src/*.ts],
gulp.series(runTypeDoc, reload)
)

gulp.task(default, gulp.series(runTypeDoc, runBrowserSync, watch))

以上 to be continued...

參考資料

  • TypeScript 官網
  • TypeScript 解決了什麼痛點? - justjavac的回答 - 知乎
  • @babel/preset-typescript
  • [譯] TypeScript 和 Babel:美麗的結合
  • The future of TypeScript on ESLint
  • Migrate the repo to ESLint #30553
  • [RFC] Migrate Jest to TypeScript #7554
  • Yarns Future - v2 and beyond #6953
  • rollup 在 17 年底就使用 TypeScript 重寫了
  • rollup-plugin-typescript2
  • tsdoc
  • typedoc
  • browser-sync
  • typedoc 插件
  • rollbar

推薦閱讀:

相關文章