🎯 什麼情境該想到我

當你猶豫「這個型別要從既有型別挖出來(Pickkeyoftypeof),還是老實再寫一份?」的時候。

⚙️ 怎麼用(步驟 / 公式)

先認識工具

語法做什麼
keyof TT 的 key 抽成聯集
typeof v取出它的型別
T[K]索引存取:取出某個屬性的型別
Pick<T, K> / Omit<T, K>挑出/排除某些屬性
interface A extends B繼承

⭐ 判準:兩邊是不是同一個關注點?

該推導 —— 共用同一個關注點

const albumTypes = { CD: "cd", VINYL: "vinyl" } as const;
type AlbumType = (typeof albumTypes)[keyof typeof albumTypes];

值和型別本來就是同一件事的兩面。解耦的話你要維護兩份會走鐘的來源

該解耦 —— 關注點不同

// ❌ 誘人但耦合:UI 元件綁死資料層的型別
type AvatarImageProps = Pick<User, "imageUrl" | "name">;
 
// ✅ 各自寫清楚
type AvatarImageProps = { imageUrl: string; name: string };

User 是資料型別、AvatarImage 是 UI 元件——責任不同、改變的理由也不同。用 Pick 之後,這個元件不只依賴 User 的形狀,還依賴它存在於 db.ts 這件事

⚠️ 書點名的心理陷阱

Pick 之所以誘人,是因為它用到比較進階的 TS 特性,讓你覺得自己很聰明。但通常,做簡單的事、讓型別保持解耦,才是比較聰明的做法。

判斷時先問自己:我選推導,是因為它真的比較好,還是因為它看起來比較厲害?

🧪 我實際套用的紀錄

  • 2026-08-28:(待填)

⚠️ 注意 / 什麼時候不適用

  • 推導是一種耦合,而且是單向的Shape 改不動 Triangle,但 Triangle 一改就會漣漪到 Shape
  • 推導鏈會變得難管。從推導型別再推導出下一個,鏈一長就沒人知道改一處會炸到哪裡。
  • 跨模組邊界時特別要想清楚:同一個模組內推導通常沒問題;跨層(資料層 → UI 層)多半該解耦。
  • 這條判準跟一般的模組設計一致——依耦合方向決定,不是依「哪個寫起來比較短」。

🔗 相關工具