前面幾天在熟悉與理解 React 的同時,也會看到一些這樣子的寫法出現在程式碼中:
function addTodo(text: string) {
// ...
}
function deleteTodo(id: number) {
// ...
}
裡面 : string、: number 的這些寫法不是 React 的語法,而是 TypeScript 在替變數標示型別。
目前的專案使用 .tsx 檔案,也是因為裡面同時包含 TypeScript 與 JSX。
TypeScript 是建立在 JavaScript 之上的程式語言,保留 JavaScript 原本的語法,並加入型別檢查。
JavaScript 中可以直接建立變數:
let text = '學習 React'
TypeScript 則可以標示這個變數應該存放字串:
let text: string = '學習 React'
如果後面把數字交給它,TypeScript 就會在開發階段提出錯誤,提醒我們數字不能指定給字串。
TypeScript 的程式最終仍然需要轉換成 JavaScript,才能交給瀏覽器執行。它的型別主要用來協助開發與檢查,轉換完成後不會保留在瀏覽器執行的 JavaScript 中。
目前 Todo List 專案已經出現幾種常見型別:
| 型別 | 內容 | 範例 |
|---|---|---|
string |
文字 | '學習 React' |
number |
數字 | 123 |
boolean |
是否成立(true、false) |
completed: false |
例如,addTodo(text: string) 代表呼叫這個函式時,傳入的 text 必須是字串。如果傳入數字,就會被 TypeScript 標示錯誤。deleteTodo(id: number) 也是相同的邏輯,因為專案使用數字作為 Todo 的 id。
來看目前專案的函式:
function deleteTodo(id: number) {
setTodos(todos.filter((todo) => todo.id !== id))
}
id: number 是在告訴 TypeScript:deleteTodo() 的 id 參數只接受數字。
如果不小心傳入字串 '1',JavaScript 仍然可能執行這段程式,但數字 1 和字串 '1' 並不是相同的值,可能造成 Todo 無法正確刪除。
TypeScript 可以在程式執行前先發現這類型別不一致的問題。因此,型別不只是讓程式碼多幾個單字,也是在記錄這個函式應該如何使用。
看到 TypeScript 一直出現型別標示,可能會以為所有變數都必須手動標示。
其實 TypeScript 具有型別推論能力,可以根據右邊的值自動判斷型別:
const text = '學習 React'
TypeScript 仍然知道 text 是 string,不需要另外寫成 const text: string = '學習 React'。
不過,在一般的函式宣告中,TypeScript 通常無法直接知道參數會收到什麼資料,因此還是要明確標示,讓 TypeScript 知道外部呼叫函式時應該傳入什麼型別。
TypeScript 官方文件:Type Inference
這裡也要注意一件事:: string 這樣的型別標示,並不會把資料轉換成字串,也不會改變 text 的內容。它只是提供一項型別資訊,表示「這裡應該是一個字串」。
如果真的需要把字串轉成數字,還是要使用 JavaScript 的方法,例如 Number('1')。型別標示與資料轉換是兩件不同的事情。
TypeScript 官方文件:The Basics
加入型別後,TypeScript 可以在開發過程中提供不少提醒,例如:
TypeScript 知道 text 是字串時,就能提示 text.trim() 這類字串可用的方法。
如果誤寫成:
text.push()
TypeScript 也會提醒 string 沒有這個方法。
不過,TypeScript 只能檢查型別,不能保證所有程式邏輯都正確。例如一個叫作 addTodo 的函式,裡面卻寫著:
console.log('刪除 Todo')
這段程式的型別可能完全沒有問題,但邏輯顯然不對。
從 API、表單或其他外部來源取得的資料,也不會因為寫上型別就自動變得正確。所以 TypeScript 比較像是在開發過程中增加一層檢查,協助減少部分錯誤,而不是讓程式從此完全不會出錯。
TypeScript 並不是要完全取代原本學過的 JavaScript,而是在 JavaScript 上增加型別系統。
目前看到的變數與函式、map()/filter()、展開運算子、if 與三元運算子、解構賦值,這些仍然都是 JavaScript;TypeScript 加入的則是像 text: string、id: number、completed: boolean 這類型別資訊。
在初次認識 TypeScript 的過程上,可以想成不是重新學習一套完全不同的語言,而是開始更明確地描述 JavaScript 中的資料。
string、number、boolean 是常見的基本型別前面看到程式碼一直出現冒號和型別時,總覺得只是讓原本的 JavaScript 變得更長。實際拆開來看後,才發現這些型別是在替資料附上使用說明,讓我能夠更清楚了解它應該怎麼被使用。