JavaScript 已經寫到滾瓜爛熟了,但畢竟 JavaScript 是一個弱型別的語言,往往有許多 bug 都從這個點衍生出來。
當提到弱型別這件事,就會說到有個強型別的 TypeScript,為什麼要用強型別呢?應該是有什麼好處吧?
今天就讓我們來討論 TypeScript!
在還只有 JavaScript 的年代,不得不說比起其他程式語言,JavaScript 真的是開發很快,讓人很有成就感的程式語言。
因為寫一行跑一行,程式碼每一行都是「實際產生功用」的,不需要事先定義 schema、enum 或 interface 等。
對於新手來說,也是一個易學好上手的語言,畢竟變數就只是個容器,這一行是 number,下一行變成 string,程式跑下去,因為 JavaScript 會自動做型別轉換,出來的結果還是有滿大機會正常的,帶給人無比的信心(?)
但也正是因為這樣鬆散的型別,容易讓新手停留在新手村好一陣子,難以成長,通常只有在踢到鐵板,在 bug 上碰了一鼻子灰時(比如 12 + 34
變成了 1234
),才會慢慢意識到,JavaScript 的方便,某種程度上也是一個陷阱。
TypeScript 是由微軟進行開發和維護的一種程式語言
TypeScript is JavaScript with syntax for types.
不管是名字還是官網都清楚告訴我們,TypeScript 就是帶了型別的 JavaScript,同時也是 JavsScript 的超集(superset),代表 TypeScript 是選擇性的,你仍然可以在 TypeScript 裡面寫 JavsScript。
目前瀏覽器與 Node.js 等環境還是不支援 TypeScript,但可以透過 TypeScript 編譯器,將程式碼編譯成 JavsScript。
TypeScript 最大的賣點自然就是「Type」啦!
但不是要你直接把所有變數都手動標上 type,那如果是這樣也太土炮了,TypeScript 最強勢的被動技能就是「型別推論」:
const a = []; // 這邊 TypeScript 就會自動幫 a 標註是個 array
// 如果 IDE 有支援自動補完,這邊只要打這樣
// 就會出現一系列 array 的 function 或 properties 讓你選
a.
// 這個判斷式會自動被畫紅線提醒,array 不該與 number 比較
if (a === 1) {
// ...
}
透過 TypeScript 提供的一些進階型別,可以先將變數的範圍限縮
為什麼要限縮?
因為每個人的習慣與風格不同,如果沒有定義出一個統一的,像是「規格文件」這樣的東西,很容易大家會各寫各的,最後要整合或重構的時候會特別痛苦。
比如同樣是要判斷「今天是否為週日」,每個人的寫法都不一樣:
let weekDay;
const today = new Date();
// 同事 1 號
if (today.getDay() === 0) {
weekDay = 'Sun';
}
// 同事 2 號
if (today.getDay() === 0) {
weekDay = 'Sunday';
}
// 同事 3 號
if (today.getDay() === 0) {
weekDay = 'sunday';
}
因此在這種情況下,通常不會針對字串直接去比對,而是先透過 enum 定義出有哪些選項,限縮可能性,其他同事也不用去翻程式碼,看說到底是大寫的 S
還是小寫的 s
,只要能夠找到那個 enum 就可以了:
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
let weekDay;
const today = new Date();
// 盡量不要用這種寫法
if (today.getDay() === 0) {
weekDay = 'Sun';
}
// 改成這樣,IDE 甚至會提醒你
if (today.getDay() === 0) {
weekDay = Days.Sun;
}
JavaScript 的物件非常自由,想要在裡面塞什麼都可以,也可以在任何時間新增、編輯、刪除裡面的 key/value,但也正是因為這麼自由,改到最後反而很難知道變成什麼樣子:
const student = {
name: 'Allen',
height: 173,
weight: 65
};
// 新增
student.bloodType = 'A';
// 編輯
student.height = '173';
// 刪除
delete student.weight;
// 如果這邊沒有 console.log 印出來
// 你可能已經不知道這位 student 變成什麼妖魔鬼怪
console.log(student);
這時就可以善用 type 或 interface:
type Student = {
name: string;
height: number;
weight: number;
bloodType?: 'A' | 'B' | 'AB' | 'O';
};
const student: Student = {
name: 'Allen',
height: 173,
weight: 65,
};
// 中間無論進行多複雜的運算,只要看著最上方的 Student type 就可以知道
// 1. student 最多只有四個 properties
// 2. height 與 weight 一定是 number
// 3. bloodType 有可能沒有值,但如果有值肯定是 A、B、AB 或 O
.js
檔案可以直接重新命名為 .ts
,不用擔心轉換到 TypeScript 需要大刀闊斧改版,可以漸進式將型別補上對於程式碼有長期品質追求的專案,或者退一步來說,即便是單純想要減少低級的型別錯誤,降低 bug 產生率,TypeScript 都是長期開發的首選。
JavaScript 在開發速度上絕對是很快的,對於快速開發、輔助功能都是適合的,但若考量到 (開發 + 維護 + 重構) 速度,TypeScript 整體上是不會輸的,如果再加上一個「令開發者安心」的分數,我想 TypeScript 是樂勝的。
同時,團隊合作也是選用 TypeScript 的好理由,定義 interface、type 或 enum 的過程,其實就像是在寫文件給隊友看了,最棒的是這文件還具有強制力,能夠讓團隊遵守一致的開發細節。
我是到今年才開始認真學 TypeScript,初次學習時,真的覺得是相見恨晚啊!因為我本身是「寫 code 焦慮型」的人,跟團隊一起寫 JavaScript 時,常常不知道
null
嗎?還是 undefined
...於是為了這些有的沒的,撞過一次兩次三次很多次 bug 之後,我養成了好多「好習慣」:
||
運算子放好預設值if
判斷式加好加滿?.
運算子加好加滿自從有了 TypeScript 之後,人生整個開闊了起來(?),不得不說,型別推論、enum、interface 那些都是實作的細節,TypeScript 真正帶給我的是 deploy 時的安心與自信!
TypeScript
PJCHENder - TypeScript
最近學完Typescript,我認為TS其實可有可無,即便大專案
也不是非得TS才能克服低級錯誤,最近那麼多AI應用其實都表明有更聰明方法
過去也不少處理手段,但多半都是自家組件與自動化來解決
不過目前要學TS最大主因他是便捷方案,因為用得早,像Angular那些很早就在用,所以滿成熟的
尤其用到很多lib的時候,都慢慢以TS做共通基礎
算是一種溝通技巧
但並非一個絕對優勢