TypeScript介紹
簡言:
確實型別要求啥的,配合Angular5功能性強大,
有一定OOP與設計概念,開發與維護度也很強。
但入門門檻其實很高,沒有一定程度的團隊,
基本上就是自己維護了,所以不要亂推專案…
其它深入的先留著,自己慢慢看
TypeScript 到底是什麼?
由 Microsoft 主打,擁有型別系統(Type System)與介面(Interface)設計的語言,TypeScript 可以想成他是在原生 JS 上包裝上一層新的語法,因此如果在 TypeScript 裡面編譯原生 JS 也是可以動作的,只不過有可能發生錯誤的原因是:TypeScript 會幫你把原生 JS 裡潛藏的 Bug 或者是沒有補清的邏輯拋出警訊(Warning)的動作。
那麼 TypeScript 本身的優點與缺點呢?
主打優勢:型別系統 Type System
另外,讀者可能會擔心 TS 會不會很複雜?老實說,它可以理解時很簡單,但是實踐起來也可能需要長時間的練習與經驗累積、動點腦筋去想最佳解法。不過也要謹記,程式語言的世界裡沒有 100% 最佳解法,只有好與更好的解法。基本上,引入 TS 的型別系統的主要目的即是:
減少 Bug 並使得維護更加容易,比如:
- 打錯字(Typo)或寫錯變數、物件性質或方法的名稱。例如:
String.prototype.toUppercase
以及String.prototype.toUpperCase
,筆者到現在還是記不了到底字串要用哪種方法才能全部轉大寫,每次都要重新上網查挺麻煩的。但有了 TypeScript,它會自動幫我們提示要用後者 —— 也就是toUpperCase
這個方法來避免錯誤。(如圖二)- 可以避免類別或物件(Class & Object)的性質與方法(Property & Method)格式錯誤。例如:我們想要定義某類別必須包含 A 以及 B 方法,但是方法的型別也有很多種類,有時候需不需要回傳新的值也是一個問題。我們可以藉由 TypeScript 自動確認我們寫的方法有沒有回傳相對應的型別與格式。
- 藉由 TypeScript 在 IDE 上的 Autocomplete Feature 來協助開發並且防止錯誤。(如圖一)

圖一:TypeScript 會自動幫我們把型別對應的方法都列出來喔

圖二:只要方法寫錯 TypeScript 甚至也會幫助我們提醒喔
平時我們開發時,必須每次讓瀏覽器(或者後端用 NodeJS )執行程式碼後 —— 一出現錯誤,馬上再回去翻看程式碼,最後經歷一番辛苦才發現可能是哪裡寫錯或者是有狀況沒有被 Handle 好。
然而,使用 TS 可以避免大部分的這些狀況,使得我們可以省去執行程式碼再去除錯的時間!
Typescript 可以和 ECMAScript 協作
更正確地來說,TypeScript 是藉由型別系統以及擴充 ECMAScript 正式定義的規範使得我們可以寫出更多漂亮的語法。就像 TS 一樣,以下將 ECMAScript 簡稱 ES。
貼心小提示
如果是初入 JavaScript 圈子的讀者,不知道 ES 的話,可以這麼想:網際網路,瀏覽器發展歷史已久,起初各大瀏覽器與公司都是實作自己版本的 JS 語法以及相對應驅動 JS 的引擎,對於互動式網頁設計的需求也不斷新增。在這種完全沒有標準規範下的混沌中誕生了 ES,也就是正式的 JS 語法規範,而現在大部分主流瀏覽器都已經完全實作出 ES5 (第五版),讀者大部分所學的 JavaScript 基礎基本上也都是在這個版本下的規範。不過如果細看 ES 發展歷史 —— ES3 跟 ES5 間隔了整整 10 年;後來差不多隔了將近 6 年的時間,ES6(又名 ES2015、Harmony,第六版)才正式釋出。這間隔實在太恐怖,因此後來規範每一年都會釋出新的 ES 版本,使得更新上不會一次有太多的新語法或新特性蹦出來。因此到今年 2019 年,已經釋出到的版本應當是 ES10 了!更新速度看起來很快,但是 ES7 ~ ES10 更新上的東西不會像 ES6 一樣多到那麼誇張。另外,我們也稱 ES11 以後的版本,也就是還未釋出的版本為 ESNext,因此聽到這些名詞也不需要覺得陌生,可以想成 JavaScript 進化到哪一個程度的指標。
網路上已經有許多關於 ECMAScript 的文章,本系列就不會再贅述細節。但最重要的是,TS 的編譯器(Compiler)可以自由地設定讓專案編譯成我們想要的 JS 版本,比如說:ES5 或 ES6 版本的 JS!(如圖三,,名為
target
的設定對應到 "es5"
的設定值)
圖三:TS 編譯器的設定檔可以讓我們自由選擇編譯 JS 的版本
另外,細看圖三中的 TS 編譯器設定檔中,也可以看到 —— 另一個名為
module
的設定可以讓我們調整編譯器要選擇編譯成 JS 的模組(Module)格式或類型。舉 NodeJS 為例,NodeJS 的模組採用 CommonJS 規範,比如:你會看到在 NodeJS 裡都是用 require
來引用模組:// 引入 File System 模組
const fs = require('fs');
fs.readFile('file.txt', (err, data) => { /* 讀取檔案後執行這邊... */ });
而 ES6 採用的是
import
語法(也就是 es2015
的格式):import React, { Component } from 'react';
因此在編譯設定上,具有蠻高的自由度呢!
更讓筆者感到好用的點是:**你可以在你的 TS 專案裡面引用 ES6 或 ES6 以後的語法並且編譯過後的結果依然是可以執行的 ES5 版本!**這使得過往我們必須手動設定類似 Babel 編譯器(專門將 ECMAScript 語法轉成 ES5 瀏覽器可以讀取的語法)來編譯 ES 的這個步驟被 TS 做掉了 —— 省了建置環境時間,讓筆者可以專注在開發上。
不過還是得提醒一下:並不是所有的 ES Feature 都有被 TS 支援。不過基本上,大部分常用的 ES6 Feature 都可以使用!
想知道特定的 ES Feature 能不能使用,請參照 ES Feature 的相容表 Compatibility Table 中,TypeScript Compiler 的那個欄位。

圖四:ES Feature 相容表
"With Great Power Comes Great Responsibility"
當然,TypeScript 儘管可以幫我們避掉一些冗贅的程序以及顯示潛藏的 Bug,不過越強大的工具,要能夠善用也是一門藝術。
以下列舉常見使用 TS 會遇到的雷(有時甚至是自己挖的,會覺得很悲哀),並且這些雷會不斷在本系列文章中展示給讀者看,因為學習一門新的技術最終目的要讓開發更流暢、易維護,因此認得錯誤或工具被誤用的模式並且改善也是學習過程中的一個重要環節:
- 最常犯的就是:過度使用 TypeScript 裡的
any
或者放寬 TS 編譯器限制使 TS 無法發揮真正效用。如果想走輕鬆路:倒不如不要用 TS 開發還比較好!但隨之而來的可能是痛苦的 Debug 過程與開發新功能連動到其他功能產生 Bug 的惡性循環! - 沒有好的軟體設計模式,再好的工具也成就不了偉大的專案,因此才會有所謂的 Best Practice(最佳實踐)以及 Antipattern(反面模式)。另外,儘管有實踐到設計模式,誤解其意義與用途也是一大錯誤。
- 熱門的套件支援 TypeScript —— 其 Type Definition 依然會有潛藏性的雷。(這不是讀者的問題,是開發套件的人對於設定型別的定義格式錯誤!)但由於熱門套件擁有眾多的相依賴模組,想要丟一個 PR 上去修改會致使其他相依賴套件有壞光光的可能性,因此我們只能靠自己:參照該套件的型別設定,設計適合自己開發的 TS 專案的型別定義檔
筆者認為,不管學習任何東西,都會有一段陣痛期。TypeScript 也會讓筆者和讀者傷透腦筋的時候,因為你要從一個完全自由的世界進到另一個具有限制性的環境,勢必會需要一定的耐性解決問題。不過 TS 的好處是,除了讓你可以認清楚,你所完全不知道的物件型別到底在各大專案或套件的背後真實面貌是什麼外,翻看那些東西的過程,搞不好也可以從中學到該專案或套件所採用的方法與程式邏輯是如何寫出來的(亦或者是發現什麼驚人的秘密!?好好奇啊!)。
總結 TypeScript
說了那麼多,不外乎就是希望讀者不要在不清楚 —— 解決什麼樣的問題或者是恍惚下隨意挑選工具去學習,到最後卻沒派上用場,投資的時間也就被浪費掉了。筆者也將舉幾個當初為何選擇 TypeScript 作為本系列文章的主題:
- 筆者認為自己在 JS 開發的過程中久了以後發現中途 Debug 的過程耗費時間不少,想要開始學習型別系統來控管好專案
- 筆者所學的各種框架與套件中,幾乎都有和 TypeScript 協作的選項(Vue CLI 3.0 才在去年時就可以建置 Vue + TS 專案)
- 筆者曾經想要打開一個開源的套件專案,結果發現都已經開始在使用 TS 來寫了。因此如果能夠徹底了解 TS,筆者就可以自由去翻看那些套件到底是怎麼寫出來的(例如一開始說的 RxJS)
- TypeScript 發展到 3.6 版的如今,仔細翻開官方的文件 —— 發現沒有筆者想像中那麼的簡單。不過經過兩週的上網學習,看了各種結合設計模式的實作,頓時覺得那些很模糊的設計模式不知覺就理解了
- TypeScript 編譯器設定清楚、入門簡單;編譯的過程、環境設定等等很輕鬆,沒有很繁複的過程
- 學習 TypeScript 過程本身很有趣,因為多了一些還沒有被 ECMAScript 正式定義下來的一些語法(比如:Decorator);然而,學習這些東西唯一要承擔的風險就是未來 ECMAScript 會不會針對該語法的定義做修改。如果被改的話,TS 對於實驗性的語法應該也會跟進。不過筆者認為風險之所以會很小的原因則是因為 —— Angular 這個框架善用了 Decorator 語法已經很久了,如果再被改掉的話,勢必會造成大量專案面臨必須更新的狀態。
另外,如果想看看別人到底怎麼說 TypeScript,可以參考看看:Why TypeScript is the best-way to Write Front-End in 2019
正文開始!
本系列文章重點
通常學習一個語言都會從語法教學開始,這裡也不例外,但僅僅只是語法教學實在是很無聊,令人難以消化。不過熟悉 TypeScript 語法對於開發任何 TS 專案是必要的,尤其是型別系統的推論與註記部分。因此本系列文章除了會著重語法與型別系統外,筆者也會儘量示範一些小程式與小型專案。
此外,TypeScript 除了結合 JS 外,OOP 語言(如 Java、C#)常見到的一些 Feature 大部分都被完整的支援。因此認識一些設計模式是必要的,所以會不定時提及到一些可以實作的技巧與用途。
另一個對於筆者來說,依舊不減其新奇感的是 Metaprogramming 的概念與應用。至於在 TypeScript 裡面到底會是怎麼樣的實現或者是什麼樣的應用呢,筆者就保留到後續的文章讓讀者自行體會吧!
讀者需要知道的事情
由於 ECMAScript 算是原生 JS 的擴充(但嚴格來講,以標準兩字形容比較洽當;然而被筆者形容成擴充的原由則是因為各種瀏覽器不能保證都有 ES 的所有特性),而 TypeScript 又是結合部分 ES Feature 以及型別系統的語言,因此本系列文章除了預設讀者應知道原生的 JS 語法與概念外,也會認為讀者至少聽過或有稍微寫過一些 ES6 或以後的一些語法(沒看過沒關係,上網查一查,花個幾分鐘到半小時至少先認識、過目一下),諸如基本的:
let
與const
以及其變數作用域- 解構語法(Destructuring)
- 箭頭函式(Arrow Functions)
- 模板字串(Template Literals)
- 匯集-展開 運算子(Rest-Spread Operator)
- 常用的 ES6 以及以後的語法等
至於會不會 ES6 Class 這一點沒關係,因為 TypeScript 裡面除了介面(Interface)的概念很重要外,類別(Class)會是另一大主角!
因此可以藉由學習 TypeScript 的 Class 再返回比對 TS 與 ES6 類別的差異 —— 也可以完整把 ES6 Class 學好。
此外,筆者也會提及
import
跟 export
的機制,畢竟 TS 擁有自己的 Namespaced Module,也因此會需要花幾個時間向讀者說明 TS Namespaces 以及 ES import
/export
的差別與應用時機為何。
你也不太需要鑽研到 Promise 或 Async-Await 那種程度的語法,這些就留給 JavaScript 社群眾多的資源為你補充學習,但在本系列文章,不太會提及到這些東西喔!但如果筆者偶爾用到這些進階語法舉例的話,會稍微為讀者說明的,這點請讀者放心。
另外,我們會還會需要用到 NodeJS 的環境,因此強烈建議還沒有 NodeJS 的讀者們,點我進去 Node 的官方網站 並且下載它。(如圖五)

圖五:NodeJS 官方網站
至於版本要選擇什麼,筆者個人認為無所謂,不過為了確保讀者有正確下載它,你可以打開你的終端機並且下這個指令來確認版本:
node --version
。圖六為筆者目前使用的 NodeJS 版本。
圖六:筆者目前的 NodeJS 版本
不過筆者為了減少本系列文章的複雜程度,除了預設讀者會使用終端機以及基本的指令外,也會預設讀者知道 NodeJS 為使用 JavaScript 開發後端專用的環境,正如瀏覽器的引擎是要讀取前端的語言進行前端的 DOM 操作(如:
window
以及 document
),在伺服端則由 NodeJS 負責讀取語言並且跟我們的作業系統進行溝通的動作(如:global
)。除此之外,讀者應當知道 Node Packages 以及 npm
的基本使用方法,諸如下載模組、建制新專案,基本的 package.json
的設定等等。開發環境 IDE 的選擇
基本上,TypeScript 由於是 Microsoft 所開發的語言,而剛好他們所開發出來的 VSCode 也是近年來熱門的 IDE(如圖七),因此筆者會在本系列文章使用 VSCode 作為主要的寫軟體工具。不過選擇 VSCode 還有更深的用意 —— VSCode 本身就已經對 TS 專案具有 AutoComplete 的支援(圖一),開發上會非常順暢;再者都是同間公司出爐的軟體,使用 TS 在 VSCode 開發上,自然也較為友善。

圖七:VSCode 官方網站
不過筆者這裡也提供兩個連結讓讀者自行選擇要使用什麼樣的開發環境,以及如何設定才能讓 TS 的開發上更加輕鬆,開發者體驗更加友善。
第一個 TypeScript 專案
首先我們可以打開你的終端機,並且到一個你想要建置 TS 專案的環境,新增一個資料夾並且進去該資料夾:
$ cd <NAVIGATE_TO_YOUR_DIRECTORY>
$ mkdir typescript-tutorial
$ cd typescript-tutorial
筆者習慣會是,每一次要新建專案時,會在檔案資料夾裡再創建新資料夾變成獨立的環境,因此資料夾規劃會變成:
typescript-tutorial
|- project-1 ...
|- project-2 ...
|- project-3 ...
|
...
因此我們再建一個名為
hello-typescript
的資料夾,並且進到該資料夾內:$ mkdir hello-typescript
$ cd hello-typescript
首先,沒有安裝過 TypeScript 的話,必須先安裝它的指令工具,記得用
-g
,因為我們要讓該指令工具可以在任何地方使用喔:$ npm install -g typescript
如果已經下載完成的話,我們可以下達:
$ tsc --init

圖八:終端機下達基本指令
此時你的專案會出現一個名為
tsconfig.json
的檔案,這就是 TypeScript 編譯器的設定檔喔,之後會再做詳細解釋。然後在同一個資料夾裡打開編輯器,此時應該會長這個樣子(圖九)。(如果你的 VSCode 不是這個色系或樣式這是沒關係的,因為筆者有特別設定過編輯器的樣式)
圖九:打開編輯器後的結果
仔細看到檔案部分有一個
tsconfig.json
檔,裡面的各種設定讀者可以稍微看看(圖十)。
圖十:
tsconfig.json
設定檔
不過我們可以先新增一個檔案名為
index.ts
,並且裡面寫一些 TypeScript 程式碼(圖十一)。
圖十一:我們的 TypeScript Hello World! 程式
接下來,在同一個檔案資料夾下,我們只要簡簡單單地下達(圖十三,第一個指令):
$ tsc
TypeScript 編譯器就會幫我們自動掃描所有
.ts
結尾的檔案並且產出 JS 檔案。
圖十二:左邊為原本的
index.ts
,右邊為編譯過後的 index.js
你可以使用 NodeJS 在後端執行編譯過後的 JS 檔案:
$ node index.js
Hello World
結果應該會印出我們的
Hello World
字串(圖十三,第二個指令後)。
圖十三:編譯並且執行我們的 JS 檔案
TypeScript V.S. 原生JS
你以為結束了嗎?真正精彩的地方在這邊,假設我們再創建一個名為
_index.js
的 JS 檔並且填入這些程式碼:const message = 'Hello World';
console.log(message.touppercase());
儘管你可能會在打
message.
的這時候出現視窗性提示(那是因為就算你不是用 TypeScript 寫,編輯器依然會幫你靜態辨別該變數型別而列出可使用的方法,圖十四),但請你就算知道出現了錯誤也先故意打成這樣子!
圖十四:就算你開發原生 JS,編輯器依然會稍微幫你列出提示性的視窗
然後再把剛剛的程式碼原封不動貼入
index.ts
裡,你會發現一個很微妙的差別。(圖十五)
圖十五:比較 TypeScript v.s. 原生 JavaScript
TypeScript 知道你犯了錯誤,因此還幫你提示你錯的地方在哪裡;但如果換作是原生 JS 的話,可就沒這麼幸運了。
如果這行程式碼藏在上百上千甚至上萬行的程式碼裡,除了直接依靠執行來確認錯誤在哪裡外,根本沒有任何提示說明錯誤到底是什麼。而 TS 幫助我們辨識該錯誤,甚至你讓滑鼠游標停留在錯誤上,就會有錯誤訊息告訴你:“是不是不小心把
toUpperCase
寫成 touppercase
呢?”(圖十六)
圖十六:TypeScript 幫你指正錯誤到底出在哪裡
如果執意去編譯這個錯誤的 TypeScript 檔案,一樣也會出現錯誤的訊息喔。(圖十七)

圖十七:TypeScript 編譯器拋出編譯錯誤的訊息
結論
到這裡,筆者也盡了基本義務將 TypeScript 的好處與特點介紹給讀者(一門技術總是要有人好好推坑啊);讀者也會發現,要建造簡單的 TypeScript 專案其實也就只有幾行指令而已,佔全文篇幅可能也不到一半而已,大部分都是說明圖片,本篇也都在分析到底 TypeScript 的優劣在哪。
本系列文章會介紹到的點總結下來有這些:
- 基本語法的 4W1H (What/Where/When/Why/How)
- 使用
tsconfig
自訂專案的編譯流程與細節 - 結合設計模式與練習一些小專案,因此也會講到如何和第三方套件協作
- 預防踩雷,讓你使用 TypeScript 也不必受驚(不過筆者在學習過程算是精彩連連,驚嚇時在後來反倒覺得又覺得是自己嚇自己)
- 進階與 Metaprogramming 的應用(這感覺不講不有趣,但講了難度又高一些,適合覺得可以再挑戰下去的工程“獅”們)
至於後續,剩下就由讀者來決定要不要跟隨本系列文章的腳步探索如何應用這門技術囉~
此外,本系列內容確定會超過 30 天。
另外,如果想要看到本系列文裡面舉的程式碼範例可以參考 Maxwell-Alexius/Iron-Man-Competition 這個 GitHub Repo 喔~寫作過程當中會不斷更新的!
這裡也會列出本系列文章的分類以及所有連結:
行前準備
工程師出征前的必備資訊呢!
Day 01. 遠征 TypeScript・行前準備 (本篇)
《前線維護》篇
駐守在 TypeScript 最前線的防禦機制到底是什麼呢?
留言
張貼留言