TypeScript 讓你更輕鬆,不再為 JavaScript 型別錯誤煩惱

Sunny.Cat :: 😸
9 min readOct 26, 2024

--

TypeScript vs JavaScript

JavaScript 一直是網頁開發的主流語言,因為它非常好寫,又有廣泛的支援,深受開發者喜愛。

不過,隨著專案變得越來越大,JavaScript 的一些缺點也開始浮現,特別是它的 動態型別 ,無法在開發階段進行型別檢查,容易帶來難以預測的錯誤。

TypeScript 就是在這樣的背景下誕生,為開發者提供了一個更安全、更可靠的選擇。

TypeScript 是由 Microsoft 推出的開源語言,在 JavaScript 基礎上加入了靜態型別檢查功能。

這讓我們可以在撰寫程式碼時就找到型別錯誤,而不是等到程式跑起來上線後才發現問題。

不過,這種彈性也帶來一些挑戰。

開發者可以選擇使用多少 TypeScript 功能,所以不同專案的程式碼風格和嚴謹度可能會差很多。

這意味著兩個 TypeScript 專案可能看起來像是完全不同的語言,也讓學習和實踐需要更多規範和指引。

特性差異

TypeScript 的基本概念:從型別檢查到編譯過程

TypeScript 的核心在於「靜態型別」。

以下是具體的範例程式碼,展示 JavaScript 和 TypeScript 在型別檢查上的差異,特別是在處理 undefined 導致程式崩潰的情境:

JavaScript 範例:執行期錯誤

未檢查 undefined 的潛在問題

在 JavaScript 中,因為沒有靜態型別檢查,你可以輕易地將 undefined 賦予變數,導致在函數運行時發生錯誤:

// JavaScript 中的範例
function greet(name) {
// 假設 name 有可能是 undefined
console.log("Hello, " + name.toUpperCase());
}

let user;
greet(user); // 執行時會報錯,因為 user 是 undefined,無法調用 toUpperCase()

問題user 變數是 undefined,當程式碼嘗試執行 name.toUpperCase() 時,會導致執行錯誤。這個錯誤只有在執行程式時才會顯現。

TypeScript 範例:開發期防錯

透過靜態型別檢查避免 undefined 錯誤

在 TypeScript 中,你可以利用靜態型別系統在開發階段就發現這類型別問題,避免潛在的執行錯誤:

// TypeScript 中的範例
function greet(name: string) {
console.log("Hello, " + name.toUpperCase());
}

let user: string | undefined;
// 這行會導致編譯錯誤,TypeScript 會提示 user 可能是 undefined
// greet(user);
// 正確的處理方式是檢查 user 是否為 undefined
if (user !== undefined) {
greet(user); // TypeScript 編譯器確認此處的 user 是 string,不會報錯
}

解決方法

在 TypeScript 中,編譯器會檢查 user 的型別並報告錯誤,提醒你 user 可能是 undefined

你可以在呼叫函數前檢查 user 的型別,這樣可以在程式碼撰寫階段就可以提早發現錯誤並更正。

為什麼有人說 TypeScript 只是 linter?

TypeScript 只是 linter,這種說法強調的是 TypeScript 的核心功能之一: 檢查程式碼的型別正確性

在 JavaScript 中,由於是動態型別語言,開發者可以自由地使用不同的資料型別。然而,這種自由也帶來了風險與麻煩,因為型別錯誤可能只有在執行時才會顯現,這大概跟 PHP 有相同的缺點。

TypeScript 的主要功能就是進行 靜態型別檢查,在編譯階段(甚至是編輯器中)就能幫助你檢測程式碼中的型別錯誤。這樣的型別檢查和 linter 的功能相似 — — 它們都是在開發階段尋找程式碼潛在錯誤的工具。

  1. 不影響程式執行結果:TypeScript 在編譯階段提醒你型別錯誤,但最終仍會將程式碼轉換成純 JavaScript。這意味著 TypeScript 對最終程式執行結果沒有影響。這點和 linter 類似,TypeScript 的作用主要是在開發階段提示潛在問題,而不會改變程式的行為。
  2. 提升開發體驗:TypeScript 強化了 JavaScript 的開發體驗,但沒有改變 JavaScript 本身的運作方式。就像 linter 幫助開發者維持程式碼格式的一致性和品質,TypeScript 則專注於維護型別一致性和安全性,讓開發者能更自信地撰寫程式碼。
  3. 檢查和輔助工具:TypeScript 的核心功能是進行型別檢查和限制,這類功能和 linter 相似,都是在開發階段提供的輔助工具,幫助開發者識別程式碼中的潛在問題。

然而,這樣的說法確實簡化了 TypeScript 的功能。

TypeScript 不僅僅是個「linter」,它還具備強大的特性,例如 型別推斷,自動推斷變數的型別,減少不必要的型別註解,以及 泛型 使函數和類別更具彈性,能夠處理不同型別的資料。

因此,說 TypeScript 只是 linter 是一種略帶玩笑意味的表達,強調的是它在 JavaScript 上提供了更好的開發體驗,而不是改變了底層語言的運作方式。

編譯原理:TypeScript 如何轉變成 JavaScript?

TypeScript 提供了型別安全的優勢,但最終執行的依然是 JavaScript 程式碼。因此,TypeScript 必須經過一個編譯過程,以下是這個流程的關鍵步驟:

  • [撰寫 TypeScript 檔案 .ts ]
  • → [初始化與環境配置]
  • → [透過編譯器進行型別檢查]
  • → [生成 JavaScript 並執行]

TypeScript 編譯流程

我們先以官方的 Node.js 專案為例說明。

  1. 撰寫 TypeScript 程式碼
  • 開發者在 .ts 檔案中撰寫 TypeScript 程式碼,並使用型別註解來強化程式碼的靜態型別檢查。

2. 初始化與配置專案

  • 初始化一個 Node.js 專案,安裝 TypeScript 套件。
  • 使用 tsc --init 指令建立 TypeScript 配置檔案 tsconfig.json
  • 根據專案需求,在 tsconfig.json 中進行配置,例如設定目標 ECMAScript 版本、模組系統、輸出路徑等。

3. 型別檢查階段

  • TypeScript 編譯器(tsc)會在程式碼撰寫階段檢查型別錯誤。
  • 任何型別錯誤都會即時顯示在 IDE 中,幫助開發者及時修正問題。

4. 編譯程式碼

  • 運行 tsc 編譯指令,TypeScript 編譯器會根據 tsconfig.json 中的配置進行編譯。
  • TypeScript 編譯器將所有型別註解移除,並將程式碼轉換成純 JavaScript。

5 . 生成 JavaScript 檔案

  • 編譯後的 JavaScript 檔案會根據配置輸出到指定的資料夾(例如 distbuild)。
  • 生成的 JavaScript 是標準格式,可以在各種支援 JavaScript 的環境中運行。

6. 執行 JavaScript 程式碼

  • 生成的 JavaScript 檔案可以直接引入到 HTML 頁面中,在瀏覽器中運行,或者在 Node.js 環境中執行。
  • 由於是標準的 JavaScript,這些檔案具有良好的跨平台兼容性。

現代化的多元編譯方式

隨著前端開發需求的增加,TypeScript 不再僅僅依賴 tsc 編譯器來進行型別檢查和轉譯,而是可以透過多種工具來達成相同效果。

除了 tsc,現代專案也常使用 Babel、Webpack、Vite 或 esbuild 等工具來編譯 TypeScript。

這些工具具有各自的優勢,例如 Babel 可以只進行語法轉譯並跳過型別檢查,適合需要快速編譯的應用,而 Webpack、Vite 和 esbuild 則可以整合模組打包、快速重載等功能,增強開發效率。

這些多元編譯方式不僅提升了 TypeScript 在不同應用場景中的彈性,還讓開發者可以根據專案需求選擇最適合的解決方案。

重要條列小結

  1. JavaScript 的局限與 TypeScript 的崛起
  • JavaScript 因為靈活性而深受喜愛,但其動態型別容易導致預期外的錯誤,特別是在大型專案中。
  • TypeScript 是在這樣的背景下誕生,通過靜態型別檢查提供更安全、可靠的開發體驗。

2. TypeScript 的核心優勢

  • 靜態型別檢查:TypeScript 在編譯階段檢查型別錯誤,減少執行時的錯誤風險。
  • 開發者彈性:開發者可以根據專案需求選擇性使用 TypeScript 功能,帶來靈活且可控的開發體驗。

3. JavaScript 與 TypeScript 的對比

  • 型別系統:JavaScript 是動態型別,TypeScript 是靜態型別。
  • 錯誤檢查:JavaScript 在執行階段檢查錯誤,而 TypeScript 在編譯階段即能發現問題。
  • 開發體驗:TypeScript 透過型別檢查與 IDE 支援,帶來更高的程式碼可讀性與重構能力。

4. TypeScript 的靜態型別範例

  • 在 TypeScript 中,透過型別註解可以在開發階段避免常見錯誤,如 undefined 導致的錯誤。
  • TypeScript 能夠提早發現和解決型別錯誤,讓程式碼更加穩定。

5. 為什麼 TypeScript 有時被稱為「linter」

  • TypeScript 的核心功能是檢查程式碼的型別正確性,類似於 linter 工具在開發階段找出潛在錯誤。
  • 但 TypeScript 不僅僅是 linter,它提供型別推斷、泛型和介面等功能,大幅提升了 JavaScript 的開發體驗。

6. TypeScript 的編譯過程

  • TypeScript 程式碼經過 tsc 編譯器檢查型別錯誤,轉換成純 JavaScript 程式碼。
  • 最終生成的 JavaScript 是標準格式,可以在任何支援 JavaScript 的環境中執行。

別怕挑戰新技能,TypeScript 會讓你的程式碼閃閃發光!

你對 TypeScript 有什麼看法或經驗呢?

歡迎在下方留言分享,讓我們一起交流成長吧!😃

--

--

Sunny.Cat :: 😸

Hi there , My name is Sunny.cat ʕ•̫͡•ʔ I am a Web developer PHP🐘Typescript🐤Golang🐻‍❄️Python🦎