iT邦幫忙

2024 iThome 鐵人賽

DAY 9
0

聯合型別

1. 聯合型別 (Union Types)

聯合型別 | ,允許一個值是一種或多種型別之一。這讓我們可以靈活地接受不同的型別輸入,而不用強制規範為單一型別。

  • 基本應用
let response: number | string;

response = 10;      // OK
response = 'Hi';    // OK
response = false;   // error
  • 延伸應用1:
    如果我們需要一個用來做加總的函式,但要預防傳入 string 型別的數字時,就可以使用聯合型別來做判斷。
function sum(x: number | string, y: number | string) :  number | string {
    if (typeof x === 'number' && typeof y === 'number') {
        return x + y;
    }
    if (typeof x === 'string' && typeof y === 'string') {
        return x.concat(y);
    }
    throw new Error('Parameters must be numbers or strings');
}

console.log(sum(1, 2));     // 3
console.log(sum(1, "2"));   // 3
console.log(sum(1, [2, 3])) // Parameters must be numbers or strings
  • 延伸應用2:
    同理,我們也可以將stringnumber型別容易被搞混的情形,應用在像是取得使用者帳號上。
// 宣告一個函式:id 可以接受 number 或 string 型別
function getId(id: number | string): string {
    return `The ID is: ${id}`;
}

console.log(getId(777));        // 777
console.log(getId("Annie922")); // Annie922

在上面這個簡單的範例中,getId 函式可以接受 numberstring 的型別值作為參數,這就是聯合型別(Union Types)的核心功能:「一個參數可以有多種可能的型別」。這讓我們能夠根據輸入不同的型別來產生不同的輸出。

  • 延伸應用3:
    在現實開發應用中,這類場景相當常見,特別是處理 API 回傳結果或使用者輸入的內容時,我們通常無法預測輸入的確切型別。為了避免出錯,我們可能會需要一個可以處理的函式,依照參數回傳錯誤訊息 (string) 或數據 (number):
function processResponse(response: number | string) {
    if (typeof response === "number") {
        console.log(`Processed response is: ${response + 10}`);
    } else {
        console.log(`Error message: ${response}`);
    }
}

processResponse(100); // Processed response is: 110
processResponse("Invalid request"); // Error message: Invalid request

這裡的 processResponse 函數根據不同型別執行不同的邏輯。當 response 是數字時,我們執行計算,當是字串時則顯示錯誤訊息。這展示了聯合型別能使程式更具適應性,並且讓型別安全的檢查更加簡便。

2. 交集型別 (Intersection Types)

交集型別 & 是一種 TypeScript 裡的進階型別,可以把多個型別結合成一個新的型別。而這個新的型別將包含所有原型別的屬性和方法,在需要結合不同物件的屬性時非常有用。

  • 基本應用
type typeAB = typeA & typeB;

順帶一提,在交集型別的宣告順序中並不會影響任何功能。意即 type typeAB = typeA & typeB;type typeBA = typeB & typeA; 具有相同的屬性。

  • 延伸應用1:
type Person = {
    name: string;
    age: number;
};

type Classmate = {
    studentNumber: number;
};

type Staff = Person & Classmate;

const staff: Staff = {
    name: "Annie",
    age: 15,
    studentNumber: 922,
};

console.log(staff); // { name: 'Annie', age: 15, studentNumber: 922 }

這裡我們將 PersonClassmate 這兩個型別合併成 Staff,並要求 Staff 同時具備 PersonClassmate 的屬性。在現實中,這種情況可能出現在我們處理擴展的物件或使用者資料時,例如某個學生同時也具有個人基本資料。

  • 延伸應用2:
type Teacher = {
    skill: string;
};

type FullStaff = Staff & Teacher;

const fullStaff: FullStaff = {
    name: "Jane",
    age: 35,
    employeeId: 5678,
    skill: "IT",
};

console.log(fullStaff);

我們可以將交集型別擴展至更複雜的場景,像是對於學校中不同老師或職員的合併需求。
在下面的範例中,可以通過交集型別將 StaffTeacher 合併成 FullStaff,它必須同時擁有姓名、年齡、員工編號以及專長。這樣的型別系統讓我們在設計程式結構時能夠更加嚴謹,並保證物件具有所有必須的屬性。

結論

TypeScript 中的聯合型別 (Union Types)和交集型別 (Intersection Types)提供了靈活且強大的型別系統,讓開發者可以在編譯時期進行更嚴格的型別檢查,從而減少程式執行時的錯誤。聯合型別使得我們能處理多樣的輸入情況,而交集型別則允許我們將不同的型別合併,實現更複雜的資料結構設計。


上一篇
Day08:TypeScript 的特殊型別
下一篇
Day10:TypeScript 的介面 (Interface) 基本概念
系列文
用 TypeScript 重新定義前端開發:30 天的實踐與思考30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言