你是否有打開過某一個專案,發現裡面的變數名稱是 a, b, c 等,完全無法透過變數直接了解其作用?此時若是使用 TypeScript,就可以透過型別的註釋,加速了解正在傳遞的數據類型,進而提高程式碼的可讀性。
同理來說,TypeScript 為了規範程式碼,提高維護,會特別著重在型別上,每個值都會有它的型別,而型別也伴隨著它本身帶有的方法,例如:string 有 indexOf()。
TypeScript 資料型別
前幾個都為 JavaScript 的原始型別(Primitive Types),在 TypeScript 同樣也有這些資料型別。我們就透過型別注釋的方式一一介紹:
Boolean
1 | let learn: boolean = true; |
因為 learn 已經是 Boolean,所以不能再將這個變數的值改為數值。1
2learn = 123; // 錯誤
learn = false; //正確
Number
數值類型支援浮點數、也可以使用十六進位、二進位、八進位。1
2
3
4let decimal: number = 5;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
String
1 | let str:string = 'learn typescript'; |
字串也可以改用模板字符串1
2let count: number = 2;
let sentence: string = `這是第 ${count} 篇文`;
這樣也就等於是1
let sentence: string = '這是第' + count + '篇文';
null
1 | let num: null; |
undefined
1 | let test: number; |
void
JavaScript 沒有 void(可視為空值),但是在 TypeScript 中,可以用 void 來表示沒有任何 return (返回值) 的函式。1
2
3
4function fn () {
console.log('learn TypeScript');
}
fn();
Array
陣列的寫法有兩種:
第一種是「型別 + 方括號」表示法,例如:number[]1
2let list: number[] = [1, '2', 3]; // 錯誤
let list2: number[] = [1, 2, 3]; // 正確
第二種則是陣列泛型(Array Generic)Array<型別>
來表示:1
2let list: Array<number> = [1, '2', 3]; // 錯誤
let list2: Array<number> = [1, 2, 3]; // 正確
Object
Object 是物件型別,也表示非原始型別(Boolean、Number、String、null、undefined)1
2let obj: object;
obj = {name: 'Tzu Hui', age: 25};
或是可以將物件內的參數一一定義型別1
2
3
4
5
6
7
8
9let obj: {
name: string,
age: number,
};
obj = {
name: 'Tzu Hui',
age: 25
};
Tuple
Tuple 是指元素陣列,Tuple 可以以固定的數量定義陣列中位置的型別1
let tupleArr: [number, string, boolean] = [2, '寫文啦', true];
如同一開始提到型別都會有自己可用的方法,因此在這邊也是會有相對應1
2console.log(tupleArr[1].substring(1)); // 正確
console.log(tupleArr[0].substring(1)); // 錯誤,因為 number 沒有 substring 方法
Enum
Enum 常被翻譯為列舉型別,用於定義一定範圍內的值。
如以下範例,將三種狀態利用 enum 做定義。在預設沒有賦予值的情況下,enum 會給這些變數對應的數字值,也就是 0, 1, 2, 3 以此類推。1
2
3
4
5enum statusCode {
success,
fail,
pending
};
上面這段在編譯後為:1
2
3
4
5
6var statusCode;
(function (statusCode) {
statusCode[statusCode["success"] = 0] = "success";
statusCode[statusCode["fail"] = 1] = "fail";
statusCode[statusCode["pending"] = 2] = "pending";
})(statusCode || (statusCode = {}));
1 | let res:statusCode = statusCode.success; |
那當有賦予值時,沒有賦予值得變數仍會依照前一個變數的值往後推 +11
2
3
4
5
6
7enum statusCode {
success = 7,
fail,
pending
};
let res:statusCode = statusCode.fail;
console.log(res); // 8
也可用數字反推1
2let status: string = statusCode[8];
console.log(status); // fail
以上介紹是 Enums 的 Numeric enums,Enums 仍有 String enums、Ambient Enums 等內容,之後再做一篇更深入的介紹。
Any
Any 為任意型別,也就是不指定型別。
在指定型別下,變數是所賦予的值是必須符合型別,但指定為 Any 時則可以自由切換
指定 string 的範例:1
2let toDayPage: string = 'two';
toDayPage = 2; // 錯誤
改為 Any 的範例:1
2let toDayPage: any = 'two';
toDayPage = 2; // 正確
Any 除了可以更換值的型別以外,設為 Any 後還可以取得屬性與方法
例如:1
2
3let anyThing: any = 'blog';
console.log(anyThing.page);
console.log(anyThing.page.count);
最後還要注意一個小地方:
因為 TypeScript 會做型別推論,但是當一開始變數沒有賦予值的話,就會定為 Any 型別。1
2let toDayPage = 'two';
toDayPage = 2; // 錯誤
下方與上方的例子差別在於,上方 toDayPage 一開始就賦予字串值,而下方式只有定義,因此在更改 toDayPage = 2 時,只有下方的 Any 不會出現錯誤,上方的則是因為型別推論被當成 string 類型而不能修改其他型別值。1
2
3
4let toDayPage: any;
toDayPage = 'two';
toDayPage = 2; // 正確
toDayPage.getPage('two');
Never
never 是代表不會出現的類型,可以用在 throw new Error。
當使用 Never 時是不可以對變數賦予其他類型的值。1
2
3
4
5
6let test: never;
test = 'learn'; // 錯誤
function error(message: string): never {
throw new Error(message);
}
小補帖 - 型別推論(Type Inference)
在 Any 的段落有提到 TypeScript 有型別推論。型別推論是 TypeScript 透過賦予的值,自動判斷該變數的型別,因此不需要做型別註釋也是可以正確執行的。
例如:1
2
3let page = 2;
page = 'two' // 錯誤
// 因為型別推論已將 page 的型別定為 Number,因此不能再賦予他 String
參考資料:
TypeScript - Basic Types
Udemy - Typescript: The Complete Developer’s Guide 2020
基礎 - TypeScript 新手指南
Typescript 學習筆記二:資料型別