第一週第一天:認識與安裝 TypeScript

第一週第一天:認識與安裝 TypeScript

由於很多抽象概念對我來說不太容易理解,筆記內有大量請 ChatGPT 把我當十歲小孩解釋概念或是教我使用相關工具的對話內容,此部分非原創。

學習資源


什麼是 TypeScript?

TypeScript 是 JavaScript 的一個超集,主要提供了型別系統對 ES6 的支援,它由 Microsoft 開發,程式碼開源於 GitHub 上。

TypeScript 是 JavaScript 的型別的超集,它可以編譯成純 JavaScript。編譯出來的 JavaScript 可以執行在任何瀏覽器上。TypeScript 編譯工具可以執行在任何伺服器和任何系統上。TypeScript 是開源的。

什麼是「超集(Superset)」?

每次看到這些說明都無法理解什麼是超集,只好請 ChatGPT 解釋給我聽:

「想像一下,你有一個玩具盒,裡面有各種顏色和形狀的積木。這些積木就像 JavaScript,是一種用來搭建東西的工具。你可以用這些積木建造很多有趣的東西,例如房子、車子、飛機等。

現在,想像你爸爸媽媽給了你一個更大的玩具盒,這個玩具盒除了原來的那些積木,還有一些新的、更酷的積木,比如有輪子的積木、發光的積木等。你可以用這些新積木和原來的積木一起建造更多更有趣的東西。這個更大的玩具盒就像 TypeScript,它包含了 JavaScript 的所有積木,還有一些額外的積木。

所以,當我們說『TypeScript 是 JavaScript 的一個超集』時,意思就是 TypeScript 包含了 JavaScript 所有功能(就像更大的玩具盒包含了原來的積木),並且還有一些額外的功能(就像新的積木)。這些額外的功能讓開發人員更容易建造更大、更複雜的『東西』(也就是程式)。」

很喜歡這樣比喻的方式,讓我能用現實的物品來理解抽象的概念。所以接下來的疑問都會以類比玩具方式請 ChatGPT 解釋。

什麼是「型別系統(Type System)」?

ChatGPT:「型別系統就像是一個幫助你分類和管理玩具的系統。想像一下,你有很多不同類型的玩具,例如小汽車、洋娃娃、積木等。要是這些玩具全都混在一起,找到你想要的玩具可能會變得很困難。所以,你會把這些玩具分類,小汽車放在一個盒子裡,洋娃娃放在另一個盒子裡,積木放在第三個盒子裡。這樣一來,當你想找某個特定的玩具時,就可以很容易地找到它。」

「在程式語言中,型別系統就是類似的概念。程式語言中有很多不同類型的資料,例如數字、文字、布林值(真或假)等。型別系統可以幫助我們分類和管理這些資料。通過將資料分類,我們可以確保我們在程式中使用資料的方式是正確的。例如,把兩個數字相加是合理的,但把一個數字和一個文字相加就可能沒有意義。」

「型別系統還可以幫助我們預防錯誤。當我們在程式中使用錯誤的資料類型時,型別系統可以提醒我們,讓我們在問題變得更嚴重之前修正它。有些程式語言(例如 TypeScript)有很強大的型別系統,可以在我們編寫程式的過程中提醒我們潛在的錯誤。而其他一些程式語言(例如 JavaScript)則有較弱的型別系統,對於資料類型的檢查較為寬鬆。」

支援 ES6(ECMAScript 2015)的意思是?

ChatGPT:「玩具公司會不斷推出新的玩具版本,每個版本都有一些新的功能和改進。這就像 JavaScript 和它的不同版本(比如 ES6)一樣,每個版本都會帶來一些新的功能和改進,讓開發人員能更好地創建程式。」

「TypeScript 支援 ES6,就像是你可以在一個玩具系統中使用不同版本的玩具。這意味著你可以使用新版本的玩具(即 ES6 的新功能),但同時也可以使用舊版本的玩具(即較早版本的 JavaScript 功能)。而且,TypeScript 會確保你用這些不同版本的玩具搭建的作品能在各種場景中正常運行。」

看完都想買玩具了(誤),概括來說 TypeScript 是:

  • 一個除了基本款玩具(JavaScript)還有炫炮款玩具的玩具盒

  • 自帶分類和管理玩具的型別系統,如果不小心分錯類時會逼逼逼提醒

  • 組合新版本(ES6)與舊版本的玩具不會出問題

這時我用《大腦喜歡這樣學》讀到的技巧「回想」,在不看筆記的情況下,腦袋想像玩具盒、積木、分類的畫面,編造一個故事複誦一遍加深記憶。

接下來我不會繼續用玩具來類比,對我來說那只是幫助理解抽象概念、輔助記憶的訣竅,繼續使用玩具來比喻有可能會混淆所學。

為什麼要用 TypeScript?

  • 定義型別就等於在撰寫函式的使用文件,一兼二顧,摸蜊仔兼洗褲

  • 即使沒有明確定義型別,TypeScript 會透過「型別推論」的規則來推斷其型別

  • 撰寫程式時就會檢查錯誤,有問題就會報錯,不需要等到執行階段才發現

  • 包含 JavaScript 的所有功能,.js 檔案可以直接將附檔名改為 .ts

  • 活躍的社群與生態系,輔助我們更快地學習和應用 TypeScript

TypeScript 的缺點?

  • 需要花更多的時間學習如何使用 TypeScript 概念與功能

  • 初期因為需要多花時間來撰寫型別的定義,會增加開發成本,但以長期來看是會降低維護成本的

  • 可能與部分第三方函式庫無法完美結合

如何安裝與使用 TypeScript?

書內提供的是全域安裝 TypeScript 的指令,但我不想安裝在全域,所以另外建立一個獨立的 typescript 專案來使用 TypeScript。

# 先切換到預計建立專案資料夾的目錄底下
mkdir typescript

# 切換到專案資料夾
cd typescript

# 建立 package.json
npm init

# 安裝 TypeScript
npm install --save-dev typescript

Hello TypeScript!

建立一個名為 hello.ts 的檔案

touch hello.ts

書中的範例程式碼複製到 hello.ts 內:

function sayHello(person: string) {
    return 'Hello, ' + person;
}

let user = 'Tom';
console.log(sayHello(user));

要如何使用專案內安裝的 TypeScript 來編譯檔案?

  1. 使用 npx 指令:npx 是一個 npm 工具,允許在不安裝全域模組的情況下運行指令。

     # 在專案根目錄底下運行
     npx tsc hello.ts
    

  2. 使用 npm scripts 指令:在專案的 package.json 文件的 scripts 新增指令來使用專案內安裝的模組。

    1. 在專案的 package.json 文件的 scripts 新增以下指令:

       {
         "scripts": {
           "build": "tsc"
         }
       }
      
    2. 在專案根目錄運行以下指令編譯 TypeScript:

       npm run build hello.ts
      

上述例子中,我們用 : 指定 person 引數型別為 string。但是編譯為 js 之後,並沒有什麼檢查的程式碼被插入進來。

這句話我大概讀了三遍才理解它的意思是:雖然我們在 hello.ts 裡定義 person 的型別是 string ,但打開編譯後的 hello.js 的檔案內可以看到,裡面並沒有任何跟型別檢查相關的程式碼。

TypeScript 只會進行靜態檢查,如果發現有錯誤,編譯的時候就會報錯。

「什麼是靜態檢查?那有動態檢查嗎?」我將心中的疑問告訴 ChatGPT 老師。

ChatGPT:「兩者的區別在於檢查的時機:靜態檢查在程式運行之前進行,而動態檢查在程式運行時進行。」

「JavaScript 主要依賴動態檢查,因為它是一門動態類型語言,意味著在運行時可以更改變量的類型。這使得在運行時檢查變量值和類型尤為重要。然而,這也意味著開發人員需要小心處理可能在運行時產生的錯誤。」

「TypeScript 通過添加靜態類型檢查為 JavaScript 帶來了更多的靜態檢查能力。這使得開發人員可以在程式運行之前找到和修復錯誤,從而提高程式的質量和穩定性。」

  • JavaScript:動態檢查,程式運行「時」進行(Runtime)

  • TypeScript:靜態檢查,程式運行「之前」進行(Compile time)

最後是驗證前面提到就算編譯出錯,仍然會產生 JavaScript 檔案(編譯結果):

如果希望 TypeScript 編譯過程中遇到錯誤時,停止產生 JavaScript 檔案的話,要在 tsconfig.jsonnoEmitOnError 選項設定為 true

{
  "compilerOptions": {
    "noEmitOnError": true,
    // 其他編譯選項...
  }
}

呼~沒想到邊學邊寫筆記有夠難的啦,謝謝看到這邊的你,我們明天見!