iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0

大家好!今天是第二十一天啦!今天要介紹的是可辨識聯集(Discriminated Union),我們在之前的介紹中,很常會使用到聯合型別,而今天要介紹的Discriminated Union會更進一步教大家聯合型別的應用喔!

順帶一提,想要複習聯合型別和交叉型別的可以點連結喔!

[Day-7]聯合型別&交叉型別


Discriminated Union

在聯合型別裡,加入一個辨識用的共同屬性,讓TypeScript(TS)可以根據這個屬性判斷目前是哪一種型別,而這個共同屬性又能稱為判別欄位。常用在API回傳結果上(成功/失敗)。

//可判別聯集範例:
type SuccessResponse = {
  status: "success"; //判別欄位
  data: string[];
};

type ErrorResponse = {
  status: "error"; //判別欄位
  errorMessage: string;
};

type APIResponse = SuccessResponse | ErrorResponse;

寫好了兩個狀態的型別,接下來要如何辨識它們呢?能夠使用ifswitch做邏輯判斷,讓TS做型別收窄喔!

function handleResponse(res: APIResponse) {
	switch (res.status) {
		//當狀態為success時,需要回傳data資料
	    case "success":
		    console.log(res.data);
		    break; 
		    //break可以結束目前的switch執行流程,避免繼續執行下一個case。
	      
	    //當狀態為error時,API需要回報錯誤資訊
	    case "error":
		    console.log("糟糕,出錯了:", res.errorMessage);
		    break;
	}
}

Discriminated Union也能夠用在兩個以上的型別:

type Loading = {
  status: "loading";
};

type Success = {
  status: "success";
  data: string;
};

type Error = {
  status: "error";
  message: string;
};

type RequestState = Loading | Success | Error;

function HandleRequest(state: RequestState) {
	switch (state.status) {
	    case "loading":
		    console.log("載入中...");
		    break;
	      
	    case "success":
		    console.log(state.data);
		    break;
	      
	    case "error":
		    console.log(state.message);
		    break;
	}
}

Discriminated Union應用

在實際開發中,也有不少地方會用到Discriminated Union:

1. API回傳結果

像上面舉的例子就是API回傳結果的應用,這邊就不再多放例子了

2. UI元件狀態

type ButtonState =
  | { type: "normal" }
  | { type: "loading" }
  | { type: "disabled" };

3. 遊戲角色狀態

type CharacterState =
  | { type: "idle" }
  | { type: "attacking"; damage: number }
  | { type: "dead"; reason: string };

這時就會發現,Discriminated Union很常用來表示不同的狀態,但其實不只適合狀態管理,只要不同型別之間有共同的辨識欄位,就可以利用它來幫助TypeScript進行型別收窄。


小結

今天介紹了Discriminated Union,雖然內容不多,但是在實際開發上,我相信很多人都用的到它的,那今天的介紹就到這邊,大家明天見啦!


上一篇
[Day-20]Type Query
下一篇
[Day-22]Module
系列文
從零開始學習TypeScript:菜鳥的入門介紹與概覽22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言