恭喜您選擇 TypeScript 作為您的第一個語言之一,您已經做出正確的決定!
您可能已經聽說 TypeScript(TS)是 JavaScript(JS)的「風味」或「變體」。TypeScript(TS)和 JavaScript(JS)之間的關係在現代程式語言中相當獨特,因此深入了解這種關係將有助於您瞭解 TypeScript 如何新增到 JavaScript。
什麼是 JavaScript?簡史
JavaScript(也稱為 ECMAScript)最初是一個瀏覽器的簡單腳本語言。在發明時,它預計用於嵌入在網頁中的簡短程式碼片段,撰寫超過幾十行的程式碼會有點不尋常。因此,早期的網路瀏覽器執行此類程式碼的速度相當慢。然而,隨著時間的推移,JS 變得越來越受歡迎,網路開發人員開始使用它來建立互動式體驗。
網頁瀏覽器開發人員透過最佳化執行引擎(動態編譯)和擴充功能(新增 API)來回應日益增加的 JS 使用量,而這反過來又讓網頁開發人員更頻繁地使用它。在現代網站中,您的瀏覽器經常執行橫跨數十萬行程式碼的應用程式。這是「網路」漫長而漸進的發展,從一個靜態頁面的簡單網路開始,演變成一個適用於各種豐富應用程式的平台。
不僅如此,JS 已變得足夠普及,可以用於瀏覽器環境之外,例如使用 node.js 實作 JS 伺服器。JS 的「隨處執行」特性使其成為跨平台開發的理想選擇。現今有許多開發人員只使用 JavaScript 來編寫他們的整個堆疊!
總之,我們有一種語言,最初設計用於快速使用,然後發展成一個功能齊全的工具,可以用來撰寫數百萬行的應用程式。每種語言都有自己的怪癖,也就是奇特和令人驚訝的地方,而 JavaScript 的卑微開端讓它有許多這樣的特質。以下是一些範例
-
JavaScript 的等號運算子 (
==
) 會強制轉換其運算元,導致意外的行為jsif ("" == 0) {// It is! But why??}if (1 < x < 3) {// True for *any* value of x!} -
JavaScript 也允許存取不存在的屬性
jsconst obj = { width: 10, height: 15 };// Why is this NaN? Spelling is hard!const area = obj.width * obj.heigth;
大多數程式語言會在發生此類錯誤時擲回錯誤,有些會在編譯期間(在任何程式碼執行之前)這麼做。在撰寫小型程式時,此類怪癖雖然惱人,但仍可控;在撰寫包含數百或數千行程式碼的應用程式時,這些不斷出現的驚喜會成為一個嚴重的問題。
TypeScript:一個靜態類型檢查器
我們之前說過,有些語言根本不允許那些有錯誤的程式執行。在不執行程式碼的情況下偵測錯誤稱為靜態檢查。根據運算值的類型來判斷什麼是錯誤和什麼不是錯誤稱為靜態類型檢查。
TypeScript 在執行前會檢查程式是否有錯誤,並根據值類型進行檢查,使其成為靜態類型檢查器。例如,上述最後一個範例會產生錯誤,原因出在 obj
的類型。以下是 TypeScript 找到的錯誤
tsTry
constobj = {width : 10,height : 15 };constProperty 'heigth' does not exist on type '{ width: number; height: number; }'. Did you mean 'height'?2551Property 'heigth' does not exist on type '{ width: number; height: number; }'. Did you mean 'height'?area =obj .width *obj .; heigth
JavaScript 的型別超集
那麼,TypeScript 和 JavaScript 有什麼關係呢?
語法
TypeScript 是一種語言,是 JavaScript 的超集:因此,JS 語法在 TS 中是合法的。語法是指我們撰寫文字以形成程式的寫法。例如,這段程式碼有一個語法錯誤,因為它缺少一個 )
tsTry
let')' expected.1005')' expected.a = (4
TypeScript 不會因為語法而將任何 JavaScript 程式碼視為錯誤。這表示您可以取得任何可運作的 JavaScript 程式碼,並將其放入 TypeScript 檔案中,而不用擔心它如何撰寫。
類型
不過,TypeScript 是型別超集,表示它新增了關於如何使用不同類型值的規則。前面關於 obj.heigth
的錯誤不是語法錯誤:它是以不正確的方式使用某種值(類型)的錯誤。
另一個範例,這是可以在瀏覽器中執行的 JavaScript 程式碼,而且它會記錄一個值
js
console.log(4 / []);
這個語法合法的程式會記錄 Infinity
。不過,TypeScript 認為數字除以陣列是無意義的運算,而且會傳出一個錯誤
tsTry
The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.2363The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.console .log (4 /[] );
你可能真的有打算將數字除以陣列,也許只是想看看會發生什麼事,但大多數時候,這是一個程式設計錯誤。TypeScript 的型別檢查器設計成允許正確的程式通過,同時盡可能捕捉到許多常見的錯誤。(稍後,我們會瞭解你可以用來設定 TypeScript 如何嚴格檢查你的程式碼的設定。)
如果你將一些程式碼從 JavaScript 檔案移到 TypeScript 檔案,你可能會看到型別錯誤,具體取決於程式碼的撰寫方式。這些可能是程式碼的合法問題,或者 TypeScript 過於保守。在整個指南中,我們將展示如何新增各種 TypeScript 語法來消除此類錯誤。
執行時期行為
TypeScript 也是一種程式語言,它保留了 JavaScript 的執行時期行為。例如,在 JavaScript 中除以零會產生 Infinity
,而不是擲出執行時期例外。原則上,TypeScript 絕不會改變 JavaScript 程式碼的執行時期行為。
這表示如果你將程式碼從 JavaScript 移到 TypeScript,它保證會以相同的方式執行,即使 TypeScript 認為程式碼有型別錯誤。
與 JavaScript 保持相同的執行時期行為是 TypeScript 的基本承諾,因為這表示你可以在這兩種語言之間輕鬆轉換,而不用擔心可能使你的程式停止運作的細微差異。
已清除的型別
粗略來說,TypeScript 編譯器在檢查完你的程式碼後,會清除類型以產生結果的「編譯」程式碼。這表示在編譯完你的程式碼後,結果的純 JS 程式碼沒有任何類型資訊。
這也表示 TypeScript 絕不會根據推論的類型來變更你的程式行為。重點是,雖然你可能會在編譯期間看到類型錯誤,但類型系統本身對你的程式在執行時的運作方式沒有任何影響。
最後,TypeScript 沒有提供任何額外的執行時期函式庫。你的程式會使用與 JavaScript 程式相同的標準函式庫(或外部函式庫),因此沒有額外的 TypeScript 特定架構需要學習。
學習 JavaScript 和 TypeScript
我們經常看到「我應該學習 JavaScript 還是 TypeScript?」這個問題。
答案是,你無法在不學習 JavaScript 的情況下學習 TypeScript!TypeScript 與 JavaScript 共用語法和執行時期行為,因此你所學的任何 JavaScript 知識都能同時幫助你學習 TypeScript。
有許多、許多的資源可供程式設計師學習 JavaScript;如果你正在撰寫 TypeScript,你不應該忽略這些資源。例如,標籤為 javascript
的 StackOverflow 問題比 typescript
多出約 20 倍,但所有 javascript
問題也適用於 TypeScript。
如果你發現自己在搜尋「如何在 TypeScript 中排序清單」之類的東西,請記住:TypeScript 是具有編譯時期類型檢查器的 JavaScript 執行時期。你在 TypeScript 中排序清單的方式與你在 JavaScript 中排序清單的方式相同。如果你找到直接使用 TypeScript 的資源,那也很棒,但不要侷限於認為你需要 TypeScript 特定的答案來解決有關如何執行執行時期任務的日常問題。
後續步驟
這是 TypeScript 日常使用語法和工具的簡要概述。從這裡,您可以