1 of 33

Bunny Chang

KKBOX Sr. Developer

TypeScript Migration

2 of 33

Agenda

2. Legacy Javascript 專案的痛點

就竟在企業環境裡的 Legacy JS 專案會遇上什麼樣的問題,讓我們開始思考是否轉換至 TypeScript 呢?

3. TypeScirpt 遷移過程中的實際經驗分享

列點分享幾個在企業環境裡進行 TypeScript Migration 時會面臨到的現實問題,以及相應解法和思考邏輯

4. Extra / Q&A

額外的心得分享以及問與答時間

1. Intorduction

自我介紹及預計遷移的專案介紹

3 of 33

自我介紹

Name

Bunny Chang

Company

KKBOX Taiwan Co., Ltd.

資歷

前端資歷三年

長期參加 COSCUP / SITCON (聽眾)� SITCON Hour of Code 講師 (只有一次)

bunnybit0121

4 of 33

What’s TypeScript!

由微軟 Anders Hejlsberg 領頭於 2012年 開發的

Anders Hejlsberg 開發過 Turbo Pascal、.Net、 C# 和 TypeScript

�是 JavaScript 的一種超集

這意味著它包含了JavaScript的所有功能,並且還增加了一些額外的功能��TypeScript 最主要的特性就是它的類型系統� TypeScript 提供了靜態類型檢查,這可以幫忙在編譯階段就找到可能的錯誤,進而提高程式碼的品質和可維護性

5 of 33

KKBOX Web Player

「基於網頁技術所生成的跨平台 Music Player」

Platforms

  • Web
  • Desktop
    • Electron.js
    • Windows / MacOS

Tech Stack

  • Vue.js 3 / VueX
  • Jest / Playwright
  • Express.js
  • JavaScript / TypeScript

Project Scale

  • 11 萬 LoC、4 年歷史
  • 開發者 3 名

6 of 33

Legacy JavaScript 專案的痛點

7 of 33

開發者低級錯誤:Typo

火眼金睛的各位,發現是哪個字拚錯了嗎?

Legacy JavaScript 專案的痛點

8 of 33

9 of 33

開發者低級錯誤:Typo

TypeScript can help !

在 App 釋出前就檢查好此類拚字錯誤

Legacy JavaScript 專案的痛點

10 of 33

Null Safety 空值安全

Legacy JavaScript 專案的痛點

11 of 33

Null Safety 空值安全

TypeScript can help !��提醒你變數可能為空,需要被處理

Legacy JavaScript 專案的痛點

12 of 33

Null Safety 空值安全

Cannot read properties of null

Cannot read properties of undefined

TypeError

為什麼點了不會動!

Legacy JavaScript 專案的痛點

為什麼是白畫面!!

13 of 33

參數到底要傳什麼?

接手的人一定知道這些參數該填啥的吧!

Legacy JavaScript 專案的痛點

14 of 33

參數到底要傳什麼?

TypeScript can help !

  • 獲得明確的傳入參數型別
  • 利用 JSDoc 標記取得更好的文件體驗

Legacy JavaScript 專案的痛點

15 of 33

難以輕鬆的重構

如果你有比這更復雜的 Legacy Code

而且你需要重新命名變數⋯

Legacy JavaScript 專案的痛點

16 of 33

難以輕鬆的重構

TypeScript can help !

  • TypeScript 能幫忙區分 Scope
  • 不會改到區域外的變數名稱

Legacy JavaScript 專案的痛點

17 of 33

Legacy JavaScript 專案的痛點

錯誤的拚字

Null Safety 空值安全

難以輕鬆的重構

傳入參數文件

18 of 33

TypeScirpt 遷移過程中的實際經驗分享

19 of 33

使用 TypeScript-ESLint 幫助維持程式碼品質

像是可以利用 naming-convention rule 來約束

在 type 為 Boolean 時必需用 is 開頭來做為變數命名

或是 Class Private Method Name 需含有 _ (underscore)

20 of 33

從高型別掌握度的元件開始 Migrate

從「高型別掌握度」的程式碼片段開始遷移

  • Level 1
    • e.g. Util Function / Web API Wrapper

  • Level 2
    • e.g. API Service / DB Store / UI Component

  • Level 3
    • e.g. Use Case / Business Logic / Store Entity

未知的型別

已知的型別

TypeScirpt 遷移過程中的實際經驗分享

21 of 33

從高掌握度的元件開始 Migrate

TypeScirpt 遷移過程中的實際經驗分享

未知的型別

已知的型別

22 of 33

從高掌握度的元件開始 Migrate

替這段 JavaScript 加註型別�是件容易的事麻?

TypeScirpt 遷移過程中的實際經驗分享

23 of 33

從高掌握度的元件開始 Migrate

TypeScirpt 遷移過程中的實際經驗分享

未知的型別

已知的型別

24 of 33

從高掌握度的元件開始 Migrate

已知

未知

TypeScirpt 遷移過程中的實際經驗分享

25 of 33

型別也需要溯源檢查

為何需要在 Runtime 驗證 API 回應型別?�確保回應數值是你所期待的型別

你期待的

你得到的

TypeScirpt 遷移過程中的實際經驗分享

26 of 33

型別也需要溯源檢查

可以使用的 Runtime Validation Tool

  • Zod.js
    • 高度成熟的 Validation Tool
    • 和 TypeScript 的相容性最佳
  • TypeBox
    • JSON Schema ⇔ TypeScript Type

TypeScirpt 遷移過程中的實際經驗分享

27 of 33

但是,要做好逃生計畫

試想,在擁有穩定使用者群的線上串流軟體,直接進行驗證會產什麼後果呢?

    • Occurrences 會淹沒你的 Error Tracking Tool (By Event 計價,很貴的!)

TypeScirpt 遷移過程中的實際經驗分享

28 of 33

但是,要做好逃生計畫

善用 Feature Toggle 來幫助你避免 Validation Error 持續灌入

    • Step 1. 利用 Remote Config 作為 Runtime feature toggle
    • Step 2. 動態切換是否驗證 API Response Schema
    • Step 3. 避免 Validation Error 淹沒 Error Tracking System

TypeScirpt 遷移過程中的實際經驗分享

29 of 33

TypeScirpt 遷移過程中的實際經驗分享

利用 TypeScript-ESLint 維持�程式碼品質

從高型別掌握度的元件開始 Migrate

善用 Feature Toggle 來降低錯誤成本

型別也需要溯源檢查

30 of 33

Summary

31 of 33

後話

  • 在 Legacy JavaScript 專案中進行 TypeScript 遷移,是極其辛苦的。�還要在「不影響既有服務品質」下進行,因此會需要「穩定小步快跑」的節奏。

  • TypeScript 的採用與否,有各種情境下的考量。�但在企業專案裡,我認為,採用高效的方式維持品質下限應是更為優先的。�
  • Language Feature vs IDE Feature
    • 也許有人在意我前述例子裡是 IDE 帶來的功能
    • 但隨著時代變化,這些IDE 相關功能,在微軟提出 Language Server Protocol (LSP) 的實作模式後,很大部份都回到語言開發者手上了。
    • 因此我會說這是 Language Feature

32 of 33

Q & A

@會眾 投影片下載網址 / QRCode�

@會眾 歡迎大家會後找我繼續討論相關議題

33 of 33

KKCompany in COSCUP !!!

We’re here~

TR 研揚大樓

📍KKCompany Website

📍KKCompany Career

快來 KKCompany 攤位領取精美好禮!