微信小程序 TypeScript 嘗試

自從去年開始在項目裏寫了一段時間 Javascript 後,感受沒有類型檢查的語言仍是不太適合我,因此一直想嘗試下 TypeScript,然而因爲項目龐大,人員協做問題,一時半會沒辦法切成 TypeScript。正好最近有小程序的需求和小程序去年 11 月開始官方支持了 TypeScript,因此拿來練練手。node

Why TypeScript?

大概是我這半年寫的 Swift 比較多,而 Swift 中的靜態類型和協議是我很喜歡的特性。正好 TypeScript 爲 JavaScript 帶來了靜態類型接口es6

可選的靜態類型

「動態類型一時爽,代碼重構火葬場「,對於我這種極度喜歡重(xia)構(gai)代碼的人來講,JavaScript 毫無類型提示,類型全靠命名猜想是極度不友好的。而 TypeScript 加上了靈活的類型系統,不只能夠編碼期檢查,還能加強代碼的可讀性,並提供了 any 類型進行緩衝。typescript

接口

接口和協議,只是不同的叫法而已,Java、C#、TypeScript 叫 Interface,Swift、Kotlin 叫 Protocol,就是一種規則聲明。項目中,和後端接口數據交互,頁面傳遞數據,數據持有,方法代理的地方,有了接口就會更加方便,易重構。TypeScript 的 Interface + JavaScript 簡單的對象就讓數據構建變得簡單又不容易出錯。小程序

小程序對 TypeScript 的支持

TypeScript 有一個很重要的東西,就是 d.ts 文件。d.ts 文件其實至關於 C 系語言裏面的 .h 頭文件,聲明瞭對外暴露的方法和屬性。而小程序官方對 TypeScript 的支持,意味着官方會維護小程序自己 API 的 d.ts 文件,也就是 typing 庫,這樣當 API 發生變更時,就能夠即時變動。segmentfault

使用也很簡單,更新微信開發者工具到最新版,在建立新項目時選擇 TypeScript 模板。後端

屏幕快照 2019-01-30 下午8.51.40

建立後,咱們能夠看到項目裏帶上了 typings 庫,以及 TypeScript 的配置文件 tsconifg。以後,保存時就不會自動編譯了,要點擊小程序工具欄的編譯按鈕才能夠。微信

這裏有一個坑,筆者電腦安裝的 TypeScript 版本是 3.2.2 版本。編譯時會被找不到全局類型 CallableFunction 和 NewableFunction。微信開發

image-20190130195121996

解決方法也很簡單,到 node_modules 路徑下的 TypeScript 包的 bin 目錄下,lib.es5.d.ts 文件裏面把這兩個類型的 Interface 拷貝到,小程序 typing 目錄下的 lib.wa.es6.d.ts 裏面就能夠了。小程序模板裏這個文件應該是拷貝 TypeScript 官方的,但沒有隨着官方升級而改變。工具

事件

視圖的事件,對應的類型筆者在 typings 中並無看到有 Interface 定義,因此只能暫時用 any,而後本身再用ui

as 轉一下 event 攜帶的數據的類型。

Page&Data

每一個 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

爲 JavaScript 編寫一個簡單的 .d.ts 文件,將須要調用的類和方法暴露出來。詳情見如何編寫一個d.ts文件

最後

雖然筆者用了 TypeScript 不久,但嚴格的檢查的確讓我在增刪改接口字段能快速全局重構,並且方法調用聯想,API 查看也方便了很多。小程序對 TypeScript 的支持平常使用開發是沒有什麼問題了,就是官方的文檔指引比較少。

相關文章
相關標籤/搜索