iT邦幫忙

2024 iThome 鐵人賽

DAY 4
0

在前一篇文章中,我們快速認識了如何進行型別註釋(Type Annotations),並介紹了型別中最基礎的原始資料型別。接下來將學習物件型別,這是開發中經常使用且較為複雜的型別之一。

在開始前,也讓我們再次複習一下型別註釋的理解圖吧!
https://ithelp.ithome.com.tw/upload/images/20240917/20140920Tk7jbEIVdg.png

物件型別(Object Types)

在 TypeScript 中,任何非原始型別的值都會被歸類為物件型別。然而,objectObject 在 TypeScript 中是不同的概念:

  • object(小寫開頭):是 TypeScript 中的一個型別,它表示非原始型別(non-primitive types),這意味著它只能接受物件型別的值,如物件({})、陣列([])、函式(function)等。不能將原始型別(如 numberstringboolean 等)賦值給 object 型別。

如果只想限制為物件型別,應該使用 object。

let obj: object;

obj = { key: 'value' };  // ok
obj = [9, 1, 7];         // ok
obj = function() {};     // ok

obj = 18;       // 錯誤:Type 'number' is not assignable to type 'object'.
obj = "ithelp";  // 錯誤:Type 'string' is not assignable to type 'object'.
  • Object(大寫開頭):是 JavaScript 中所有物件的內建類別(built-in class),所有物件都繼承自 Object。因此,Object 可以接受所有型別,包括原始型別和物件型別。換句話說,所有的值在 JavaScript 中都是 Object 的實例,因為所有的物件都繼承了 Object.prototype

如果可以允許變數接受任何型別,則使用 Object 或直接使用更廣泛的 anyunknown

let obj: Object;

obj = { key: 'value' };  // ok
obj = [9, 1, 7];         // ok
obj = function() {};     // ok

obj = 18;                // ok
obj = "ithelp";           // ok

下面是一些範例,展示如何在 TypeScript 中使用 object 型別。

1. 基本使用

  • 最基本的宣告一個 object
let employee: object = {};

employee = {
    firstName: 'Annie',
    age: 18,
    jobTitle: 'Web Developer'
};

console.log(employee);

// {
//   firstName: 'Annie',
//   age: 18,
//   jobTitle: 'Web Developer'
// }
// Type '{ firstName: string; age: number; jobTitle: string }' is not assignable to type 

2. 明確定義物件屬性的型別

  • 明確指定 key-value 的屬性
    但如果我們需要更精確地定義 employee 的屬性,TypeScript 會提醒我們沒有完整定義 key-value 的型別。所以可以使用明確的型別註釋,這樣的方式使得 TypeScript 編譯器能夠知道 employee 的具體結構,從而能更好地進行靜態檢查。
let employee: {
    firstName: string;
    age: number;
    jobTitle: string;
};
  • 或者直接在物件宣告時,用 {} 定義型別,讓語法更簡潔。
const employee: {
    firstName: string;
    age: number;
    jobTitle: string;
} = {
    firstName: 'Annie',
    age: 18,
    jobTitle: 'Web Developer'
};

3. 不合法的使用

  • 如果嘗試將一個不符合型別的值賦給物件,TypeScript 會報錯
employee = "Tina";
// Type '"Tina"' is not assignable to type 'object'.
  • 同樣地,若嘗試存取不存在的屬性,也會報錯
console.log(employee.lastName);
// Property 'lastName' does not exist on type 'object'.

4. 新增屬性

  • 如果需要新增屬性與值給 object
    用方法2是最完整的寫法,推薦早期就養成習慣唷。
// 方法1
employee = {
    firstName: 'Annie',
    lastName: 'Lin',
    age: 18,
    jobTitle: 'Web Developer'
};

// 方法2
let employee: {
    firstName: string;
    lastName: string;
    age: number;
    jobTitle: string;
} = {
    firstName: 'Annie',
    lastName: 'Lin',
    age: 18,
    jobTitle: 'Web Developer'
};

console.log(employee);

// {
//   firstName: 'Annie',
//   lastName: 'Lin',
//   age: 18,
//   jobTitle: 'Web Developer'
// }

5. 可選屬性

  • 如果有個欄位不一定存在:
    有時候,我們會遇到不一定存在的屬性。在這種情況下,可以使用可選屬性,這是透過在屬性名稱後面加上問號(?)來實現的。例如,假設我們希望 startDate 是一個可選屬性
let employee: {
    firstName: string;
    lastName: string;
    age: number;
    jobTitle: string;
    startDate?: Date; // 可選屬性
} = {
    firstName: 'Annie',
    lastName: 'Lin',
    age: 18,
    jobTitle: 'Web Developer'
};

  • 如果需要使用可選的欄位時,則可以這樣指定:
    startDate 是可選的,因此在初始化物件時可以選擇不包含該屬性。當需要指定 startDate 時,可以這樣使用
employee.startDate = new Date(); // 加上 startDate 屬性

結語

以上是 TypeScript 中物件型別的基本使用方法。在實際開發中,物件型別比原始型別更為複雜且靈活。此外,TypeScript 也支持更多進階的型別系統,例如物件型別的擴展(如 interface)、特殊型別(如 anyunknown)、聯合型別和交叉型別等。我們將在後續的文章中詳細介紹這些型別的使用方式。


上一篇
Day03:TypeScript 之基礎型別(Primitive Types)
下一篇
Day05:TypeScript 的陣列型別(Array Types)
系列文
用 TypeScript 重新定義前端開發:30 天的實踐與思考30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言