型別系統(Type System)
是 TypeScript 提供的核心功能,它建立起了型別的宇宙
本篇要來介紹型別系統中在基本不過的概念 -「型別註釋
」、「型別推斷
」
在進入正題之前,先來回憶一下 JavaScript 有哪些型別呢?
原始型別 | 物件型別 |
---|---|
String | Array |
Number | Object |
Boolean | Function |
Null | Date |
Undefined | RegExp |
BigInt | Error |
Symbol | Map, Set, WeakMap, WeakSet |
💡 有別於 JS 的型別是固定的。TypeScript 型別系統有個很強大的功能是可擴充型別
,也就是可以自訂義型別,像是 Interface(介面)
, Enum(枚舉)
, Generics(泛型)
... 等。後續的章節會逐一介紹
TypeScript 的型別系統裡除了涵蓋上方提到的原始型別外,還包含了非常多~~的型別和定義方式,等等要講的 型別註釋 (Type Annotations)
也是其中之一
如下圖整理
定義:明確指定
變數或參數的型別。TS 的型別註釋是在變數或參數後
用冒號 (:) 表示,例如:
: string
: boolean
: number
: any
: void
: [string, number]
: number[]
// ...略
The type names String, Number, and Boolean (starting with capital letters) are legal, but refer to some special built-in types that will very rarely appear in your code. Always use string, number, or boolean for types.
官方提到若要使用 String, Number, Boolean 這種大寫開頭
的註釋方式是可行的,但不建議使用
原因是大寫會指向 JS 的物件,例如 String 是指向內建的 String 物件,除非你需要取用該物件裡提供的方法,否則寫 string, number, boolean 就好了👍🏻👍🏻👍🏻
讓 TypeScript 自動推斷
型別,可減少定義型別,使 code 更簡潔
1.【型別註釋】當傳入的值不符合定義的型別時,在開發中就會報錯
const playSong = (artistName: string, year: number) => {
return `In ${year}, everyone love ${artistName}.`;
};
const artist: string = "Lady Gaga";
const year: number = 2024;
playSong(artist, year);
playSong('Taylor Swift', '2024'); // ❌ Argument of type 'string' is not assignable to parameter of type 'number'.
2.【型別推斷】當有一個變數的值參雜了多種型別值,TS 會計算出這個變數的「Best common type」。這個範例的「Best common type」會是 number
或 null
let x = [0, 1, null]; // let x: (number | null)[]
3.【型別推斷】a 和 b 已經有指定型別,result 為兩者相乘,從上下文可以推斷其型別也會是數字(數字 * 數字 = 數字),所以也沒什麼必要再指定型別
function multiple(a: number, b: number) {
const result = a * b; // 型別推斷 const result: number
return result;
}
4.【型別推斷】:「變數宣告」和「變數賦值」兩者分開寫會有不同的結果,先宣告後賦值會被推斷為 :any
(any 後續章節會提到)
let a; // 推斷為 :any
a = 1;
a = 2;
a = '3'; // ✅ Pass
let b = 1;
b = 2;
b = '3' // ❌ Type 'string' is not assignable to type 'number'.
在撰寫這篇文時發現一個有趣的Bug,如下圖
完整錯誤: error TS2451: Cannot redeclare block-scoped variable 'name'.
這支檔案內明明只有變數 name,也沒有自行宣告一樣的全域變數,為何還會跟我說 redeclare 呢?
這問題的原因是 script 是全域範圍 (global scope),和模組 (module) 不同
想知道詳細解法請看 https://www.jianshu.com/p/78268bd9af0a
TypeScript Github Isues 裡面提到的 moduleDetection
超神!! 在 tsconfig.json
中把它的值改為 force
就正常了
每天講的內容有推到 github 上喔