自從去年開始在項目裏寫了一段時間 Javascript 後,感受沒有類型檢查的語言仍是不太適合我,因此一直想嘗試下 TypeScript,然而因爲項目龐大,人員協做問題,一時半會沒辦法切成 TypeScript。正好最近有小程序的需求和小程序去年 11 月開始官方支持了 TypeScript,因此拿來練練手。node
大概是我這半年寫的 Swift 比較多,而 Swift 中的靜態類型和協議是我很喜歡的特性。正好 TypeScript 爲 JavaScript 帶來了靜態類型和接口。es6
「動態類型一時爽,代碼重構火葬場「,對於我這種極度喜歡重(xia)構(gai)代碼的人來講,JavaScript 毫無類型提示,類型全靠命名猜想是極度不友好的。而 TypeScript 加上了靈活的類型系統,不只能夠編碼期檢查,還能加強代碼的可讀性,並提供了 any 類型進行緩衝。typescript
接口和協議,只是不同的叫法而已,Java、C#、TypeScript 叫 Interface,Swift、Kotlin 叫 Protocol,就是一種規則聲明。項目中,和後端接口數據交互,頁面傳遞數據,數據持有,方法代理的地方,有了接口就會更加方便,易重構。TypeScript 的 Interface + JavaScript 簡單的對象就讓數據構建變得簡單又不容易出錯。小程序
TypeScript 有一個很重要的東西,就是 d.ts 文件。d.ts 文件其實至關於 C 系語言裏面的 .h 頭文件,聲明瞭對外暴露的方法和屬性。而小程序官方對 TypeScript 的支持,意味着官方會維護小程序自己 API 的 d.ts 文件,也就是 typing 庫,這樣當 API 發生變更時,就能夠即時變動。segmentfault
使用也很簡單,更新微信開發者工具到最新版,在建立新項目時選擇 TypeScript 模板。後端
建立後,咱們能夠看到項目裏帶上了 typings 庫,以及 TypeScript 的配置文件 tsconifg。以後,保存時就不會自動編譯了,要點擊小程序工具欄的編譯按鈕才能夠。微信
這裏有一個坑,筆者電腦安裝的 TypeScript 版本是 3.2.2 版本。編譯時會被找不到全局類型 CallableFunction 和 NewableFunction。微信開發
解決方法也很簡單,到 node_modules 路徑下的 TypeScript 包的 bin 目錄下,lib.es5.d.ts 文件裏面把這兩個類型的 Interface 拷貝到,小程序 typing 目錄下的 lib.wa.es6.d.ts 裏面就能夠了。小程序模板裏這個文件應該是拷貝 TypeScript 官方的,但沒有隨着官方升級而改變。工具
視圖的事件,對應的類型筆者在 typings 中並無看到有 Interface 定義,因此只能暫時用 any,而後本身再用ui
as 轉一下 event 攜帶的數據的類型。
每一個 Page 對象,在 typing 裏是這麼定義的。
declare const Page: Page.PageConstructor
interface PageConstructor {
<D extends IAnyObject, T extends IAnyObject & PageInstance>(
options: PageInstance<D, T> & T
): void
}
複製代碼
也就是說,它支持 D 和 T 兩個範型。這兩個範型是什麼呢?小程序裏,Page 是這麼寫的。
Page({});
複製代碼
也就是說,options 參數就是一個 PageInstance,範型也被傳入了。
interface PageInstance<D extends IAnyObject = any, T extends IAnyObject = any> extends PageInstanceBaseProps<D>
複製代碼
PageInstance 裏面定義了 Page 聲明週期的方法,並且繼承自 PageInstanceBaseProps,並將範型 D 傳入。
interface PageInstanceBaseProps<D extends IAnyObject = any> {
data?: D
//...
}
複製代碼
因此這個 D 範型,其實就是 data 的類型接口。由於 data 不是必須實現的,因此這裏是可選型 ?。
那麼 T 是什麼呢?
T extends IAnyObject & PageInstance
複製代碼
T 其實就是對 PageInstance 的拓展,PageInstance 是 Page 的實例接口,那麼 T 其實就是在 Page 裏面 this 的類型接口了,也就是說,須要在 Page 裏新增的方法和屬性,都在 T 裏定義。
因此,對於一個普通頁面咱們能夠聲明兩個接口,一個表明 data, 一個表明 page,舉個例子。
interface IIntroPage {
nextButtonTap(event: any): void;
isLoading: boolean;
}
interface IIntroData {
test: string;
}
Page<IIntroData, IIntroPage>({
isLoading: false,
nextButtonTap(event: any) {
this.isLoading = true;
}
});
複製代碼
若是這個頁面不須要 data 或者不須要擴展 page,用 IAnyObject 代替 D 或者 T 便可。
interface PageInstanceBaseProps<D extends IAnyObject = any> {
data?: D
setData?<K extends keyof D>(
data: D | Pick<D, K> | IAnyObject,
callback?: () => void
): void
}
複製代碼
同時,因爲 setData 和 data 都被聲明爲可選項,使用時須要加上!,this.setData!({})
和 this.data!
。
其餘就沒什麼了,用上 TypeScript 以後,官方的 API 均可以直接看參數和返回值的類型,不再用去查文檔猜想類型了。
爲 JavaScript 編寫一個簡單的 .d.ts 文件,將須要調用的類和方法暴露出來。詳情見如何編寫一個d.ts文件。
雖然筆者用了 TypeScript 不久,但嚴格的檢查的確讓我在增刪改接口字段能快速全局重構,並且方法調用聯想,API 查看也方便了很多。小程序對 TypeScript 的支持平常使用開發是沒有什麼問題了,就是官方的文檔指引比較少。