iT邦幫忙

2025 iThome 鐵人賽

DAY 14
0

昨天我們學了 型別守衛(Type Guards)

今天來看看 TypeScript 內建的「型別小工具」。

它們能讓你不用重寫型別,就能快速得到你想要的型別變化。


1. 什麼是 Utility Types?

Utility Types 是 TypeScript 內建的一組型別變換工具。你可以把它想成「型別的函式」,輸入一個型別,產生一個新型別。

好處:

  • 節省重複定義的時間
  • 保持型別與原始資料結構同步
  • 增加可讀性

2. 常用 Utility Types 清單(依使用頻率)

2.1 Partial<T>

讓 T 的所有屬性變成可選的(?)。

type User = { id: string; name: string; email: string };

type UserUpdate = Partial&lt;User&gt;;
// 等同於 { id?: string; name?: string; email?: string }

function updateUser(id: string, update: UserUpdate) {}
updateUser("u1", { name: "New Name" });

用途:更新部分資料(PATCH API)。


2.2 Required<T>

把所有可選屬性變成必填。

type User = { id?: string; name?: string };

type CompleteUser = Required&lt;User&gt;;
// { id: string; name: string }

用途:確保在某些流程後資料是完整的。


2.3 Readonly<T>

讓屬性不可修改。

type Config = { apiUrl: string; port: number };

const cfg: Readonly&lt;Config&gt; = { apiUrl: "https://api.com", port: 8080 };
cfg.port = 3000; // ❌ Cannot assign to 'port'

用途:防止意外修改設定物件。


2.4 Pick<T, K>

挑出 T 中的部分屬性。

type User = { id: string; name: string; email: string };

type UserPreview = Pick&lt;User, "id" | "name"&gt;;
// { id: string; name: string }

用途:列表畫面只需要部分資料時。


2.5 Omit<T, K>

刪掉 T 中的某些屬性。

type User = { id: string; name: string; email: string };

type UserWithoutEmail = Omit&lt;User, "email"&gt;;
// { id: string; name: string }

用途:過濾不必要或敏感資料。


2.6 Record<K, T>

建立一個以 K 為 key、T 為值的型別。

type Role = "admin" | "user" | "guest";

type Permissions = Record&lt;Role, string[]&gt;;
// { admin: string[]; user: string[]; guest: string[] }

用途:權限表、設定映射。


2.7 Exclude<T, U>

從 T 中排除掉 U。

type Status = "success" | "error" | "pending";

type Finished = Exclude&lt;Status, "pending"&gt;;
// "success" | "error"

用途:移除不需要的型別成員。


2.8 Extract<T, U>

從 T 中挑出 U。

type Status = "success" | "error" | "pending";

type Active = Extract&lt;Status, "pending"&gt;;
// "pending"

用途:篩選符合條件的型別成員。


2.9 NonNullable<T>

排除 nullundefined

type MaybeString = string | null | undefined;

type DefiniteString = NonNullable&lt;MaybeString&gt;;
// string

用途:在保證值不為空時使用。


2.10 ReturnType<T>

取得函式的回傳型別。

function getUser() {
  return { id: "u1", name: "Alice" };
}

type User = ReturnType&lt;typeof getUser&gt;;
// { id: string; name: string }

用途:自動同步函式回傳型別與變數型別。


2.11 Parameters<T>

取得函式的參數型別(Tuple)。

function login(user: string, pass: string) {}

type LoginParams = Parameters&lt;typeof login&gt;;
// [user: string, pass: string]

用途:重用函式參數型別。


3. 實務綜合案例:更新使用者資料 API

type User = { id: string; name: string; email: string; createdAt: Date };

// 更新 API 只接受部分資料
type UpdateUserDto = Partial&lt;Omit&lt;User, "id" | "createdAt"&gt;&gt;;

function updateUser(id: string, data: UpdateUserDto) {
  // ...
}

updateUser("u1", { name: "New Name" }); // OK
updateUser("u1", { createdAt: new Date() }); // ❌ createdAt 已被移除

4. 心法小結

  • Partial / Required / Readonly → 改變屬性必選與可修改性
  • Pick / Omit → 挑選或刪除屬性
  • Record / Exclude / Extract / NonNullable → 型別集合運算
  • ReturnType / Parameters → 從函式取得型別

上一篇
Day 13|型別守衛(Type Guards):幫 TypeScript 看懂你的 if/else
系列文
我與型別的 30 天約定:TypeScript 入坑實錄14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言