TypeScript 基本型別
前言
這一篇文章,主要來筆記 TypeScript 的基本型別;在進到正式內容前,也先透過一個簡單範例,來說明 TypeScript 是怎麼幫助我們減少開發錯誤的。
以原本 JavaScript 變數的特性來說,它可以被賦予任何的資料型態,在程式不複雜時,這樣的自由跟彈性比較不會帶來什麼問題;但如果程式開始變複雜時,就容易會有意外的狀況(Bug)。如下範例:
1 |
|
從上方範例中,我們可以看到程式碼偏離了預期(數字相加、回傳數字),而這樣就會導致開發的錯誤。
使用 TypeScript 來撰寫,就可以明確指定函式的 a、b 參數都必須是 number 型別,而回傳結果也是 number 型別,來達到數字相加的預期結果;如果我們將參數傳入不同型別(例如:字串),在編譯過程或者 VSCode 的功能上,就會提醒我們出現錯誤。而這樣的型別設置,就能在「開發階段」時就提醒我們型別出現錯誤了。
1 |
|
原始型別(Primitive Types)
在 JavaScript 中有七種原始型別,分別是:
- String
- Number
- Boolean
- Null
- Undefined
- Symbol:ES6/2015 才有,可用於建立獨一無二的值
- BigInt:ES11/2020 才有,用於數值非常大的狀況
(Symbol、BigInt 基本會較少使用到,我自己目前在專案開發中也沒有用過)
宣告變數加上 TypeScript 的型別定義時,規則是這樣的:let 變數名稱:資料型態 = 資料
1 |
|
陣列型別(Array Type)
陣列型別可以用來定義一組相同型別的元素。TypeScript 提供兩種常見的語法來做定義:
let 變數名稱: 型別[] = 陣列資料
let 變數名稱: Array<型別> = 陣列資料
:這種方式是使用泛型來定義,這邊可約略先知道有這樣的方式,而關於泛型這個概念的詳細,會在後面章節補充。
第一種語法範例:
1 |
|
第二種語法範例:
1 |
|
TypeScript 支援多維陣列的方式,如下方範例的二維陣列(內容補充):
1 |
|
元組型別(Tuple Type)
元組是 TypeScript 中的一種特殊陣列,它與一般陣列不同的是,元組這個概念允許我們在陣列中包含「不同型別」的元素,但每個元素的型別和順序都是被嚴格定義的(陣列長度也是)。
範例:
1 |
|
如果有遇到特殊狀況,需要明確定義資料結構的順序和型別時,也許就會使用到元組這個概念。
(不過目前思考了過去專案,這樣狀況應該是不常見低~)
物件型別(Object Type)
物件型別可以用來定義物件的結構,確保每個屬性都有正確的型別。
1 |
|
選擇性屬性(Optional Properties)
有時我們並不需要每個屬性都是「必須」提供的,像是有些資訊可以依照使用者需求(喜好)來提供,這時我們可以使用 ?
來讓某些屬性變為選擇性屬性。
user 相關範例如下,因為我們將 phoneNumber?
多設置了選擇性屬性,所以不論在 user1 沒有提供 phoneNumber
的資訊,或者 user2 有提供 phoneNumber
的資訊,都不會出現 TypeScript 的相關警告。
1 |
|
唯讀屬性(Readonly Properties)
除了在物件使用選擇性屬性,TypeScript 也提供了 readonly
關鍵字,讓某些屬性只能讀取,不能再修改。
範例:
1 |
|
函式型別(Function Type)
在函式型別中,我們可以定義函式的輸入(參數)以及輸出型別,避免一些意外的型別錯誤。當我們定義函式型別時,會使用 :
來指定型別。
函式陳述式(Function Declaration)
下方範例是陳述式函式的定義,由這樣的定義可確保:
- a 和 b 參數必須是
number
型別 - 函式回傳值必須是
number
型別
1 |
|
函式表達式(Function Expression)
函式表達式也是常見的定義方式,將函式作為值指派到變數中。範例如下:
1 |
|
不過以上的寫法,其 sum2 這個變數是透過「推論」出來的,關於「推論」這個概念,將會在 TypeScript 系列的下一篇提到。簡單來說,當我們沒有對變數明確定義型別時,TypeScript 會幫我們根據內容去推論出型別。
如果要更明確定義 sum2 的型別,可以如下範例:
1 |
|
(a: number, b: number) => number
在這邊的寫法上,我們會看到「箭頭」的方式來表示回傳的型別,因為前面 sum2 變數已經有使用到 :
,所以為了不混淆,這邊是使用箭頭的方式。需注意這個箭頭的方式,跟 ES6 的箭頭函式是完全沒有關係的。(剛開始看到這樣的寫法時,我覺得滿混亂的。)
聯合型別(Union Types)
聯合型別使用 | 運算符表示變數或參數可以接受多種可能的型別。
範例如下:
1 |
|
假設某個情境,我們需要對不同型別的輸入,分別做不同的處理時,就能在函式的參數中使用聯合型別,然後再配合 typeof
判斷。如下範例:
1 |
|
任意型別(Any)
如果變數被定義 any 這個型別,則表示它可以是任何型別;不過既然我們撰寫 TypeScript 就是為了對型別的處理更為嚴謹,所以使用 any 需特別謹慎,也比較不建議使用哩。
有幾個情境,可以謹慎使用 any 型別(過渡):
- 當從外部 API 獲取的資料結構不明確,或者有可能變化時
- 資料狀況比較複雜,無法在初期準確定義型別時
- 從 JavaScript 專案遷移到 TypeScript 的過渡期
1 |
|
結語
以上是 TypeScript 系列的第二篇,筆記跟整理了基本型別。在這個系列的第三篇內容,預計是要來說 TypeScript 的核心概念:註記與推論。
參考資料:
- 六角學院 TypeScript 30 天課程
- 書籍:<讓 TypeScript 成為你全端開發的 ACE!>
Photo by Safar Safarov on Unsplash