TypeScript - 資料型別 和 Type Annotations

TypeScript - 資料型別 和 Type Annotations

你是否有打開過某一個專案,發現裡面的變數名稱是 a, b, c 等,完全無法透過變數直接了解其作用?此時若是使用 TypeScript,就可以透過型別的註釋,加速了解正在傳遞的數據類型,進而提高程式碼的可讀性。

同理來說,TypeScript 為了規範程式碼,提高維護,會特別著重在型別上,每個值都會有它的型別,而型別也伴隨著它本身帶有的方法,例如:string 有 indexOf()。

TypeScript 資料型別

前幾個都為 JavaScript 的原始型別(Primitive Types),在 TypeScript 同樣也有這些資料型別。我們就透過型別注釋的方式一一介紹:

Boolean

1
let learn: boolean = true;

因為 learn 已經是 Boolean,所以不能再將這個變數的值改為數值。

1
2
learn = 123; // 錯誤
learn = false; //正確

Number

數值類型支援浮點數、也可以使用十六進位、二進位、八進位。

1
2
3
4
let decimal: number = 5;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;

String

1
2
let str:string = 'learn typescript';
str = 'TypeScript';

字串也可以改用模板字符串

1
2
let count: number = 2;
let sentence: string = `這是第 ${count} 篇文`;

這樣也就等於是

1
let sentence: string = '這是第' + count + '篇文';

null

1
2
3
let num: null;
num = 1; // 錯誤
num = null; // 正確

undefined

1
2
3
4
5
let test: number;
console.log(test); // 錯誤

let test2: undefined;
console.log(test2); // 正確

void

JavaScript 沒有 void(可視為空值),但是在 TypeScript 中,可以用 void 來表示沒有任何 return (返回值) 的函式。

1
2
3
4
function fn () {
console.log('learn TypeScript');
}
fn();

Array

陣列的寫法有兩種:
第一種是「型別 + 方括號」表示法,例如:number[]

1
2
let list: number[] = [1, '2', 3]; // 錯誤
let list2: number[] = [1, 2, 3]; // 正確

第二種則是陣列泛型(Array Generic)Array<型別> 來表示:

1
2
let list: Array<number> = [1, '2', 3]; // 錯誤
let list2: Array<number> = [1, 2, 3]; // 正確

Object

Object 是物件型別,也表示非原始型別(Boolean、Number、String、null、undefined)

1
2
let obj: object;
obj = {name: 'Tzu Hui', age: 25};

或是可以將物件內的參數一一定義型別

1
2
3
4
5
6
7
8
9
let obj: { 
name: string,
age: number,
};

obj = {
name: 'Tzu Hui',
age: 25
};

Tuple

Tuple 是指元素陣列,Tuple 可以以固定的數量定義陣列中位置的型別

1
let tupleArr: [number, string, boolean] = [2, '寫文啦', true];

如同一開始提到型別都會有自己可用的方法,因此在這邊也是會有相對應

1
2
console.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
5
enum statusCode {
success,
fail,
pending
};

上面這段在編譯後為:

1
2
3
4
5
6
var statusCode;
(function (statusCode) {
statusCode[statusCode["success"] = 0] = "success";
statusCode[statusCode["fail"] = 1] = "fail";
statusCode[statusCode["pending"] = 2] = "pending";
})(statusCode || (statusCode = {}));

1
2
let res:statusCode = statusCode.success;
console.log(res); // 0

那當有賦予值時,沒有賦予值得變數仍會依照前一個變數的值往後推 +1

1
2
3
4
5
6
7
enum statusCode {
success = 7,
fail,
pending
};
let res:statusCode = statusCode.fail;
console.log(res); // 8

也可用數字反推

1
2
let status: string = statusCode[8];
console.log(status); // fail

以上介紹是 Enums 的 Numeric enums,Enums 仍有 String enums、Ambient Enums 等內容,之後再做一篇更深入的介紹。

Any

Any 為任意型別,也就是不指定型別。
在指定型別下,變數是所賦予的值是必須符合型別,但指定為 Any 時則可以自由切換
指定 string 的範例:

1
2
let toDayPage: string = 'two';
toDayPage = 2; // 錯誤

改為 Any 的範例:

1
2
let toDayPage: any = 'two';
toDayPage = 2; // 正確

Any 除了可以更換值的型別以外,設為 Any 後還可以取得屬性與方法
例如:

1
2
3
let anyThing: any = 'blog';
console.log(anyThing.page);
console.log(anyThing.page.count);

最後還要注意一個小地方:
因為 TypeScript 會做型別推論,但是當一開始變數沒有賦予值的話,就會定為 Any 型別。

1
2
let toDayPage = 'two';
toDayPage = 2; // 錯誤

下方與上方的例子差別在於,上方 toDayPage 一開始就賦予字串值,而下方式只有定義,因此在更改 toDayPage = 2 時,只有下方的 Any 不會出現錯誤,上方的則是因為型別推論被當成 string 類型而不能修改其他型別值。

1
2
3
4
let toDayPage: any;
toDayPage = 'two';
toDayPage = 2; // 正確
toDayPage.getPage('two');

Never

never 是代表不會出現的類型,可以用在 throw new Error。
當使用 Never 時是不可以對變數賦予其他類型的值。

1
2
3
4
5
6
let test: never;
test = 'learn'; // 錯誤

function error(message: string): never {
throw new Error(message);
}

小補帖 - 型別推論(Type Inference)

在 Any 的段落有提到 TypeScript 有型別推論。型別推論是 TypeScript 透過賦予的值,自動判斷該變數的型別,因此不需要做型別註釋也是可以正確執行的。

例如:

1
2
3
let page = 2;
page = 'two' // 錯誤
// 因為型別推論已將 page 的型別定為 Number,因此不能再賦予他 String

參考資料:
TypeScript - Basic Types
Udemy - Typescript: The Complete Developer’s Guide 2020
基礎 - TypeScript 新手指南
Typescript 學習筆記二:資料型別

評論

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×