iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0
JavaScript

我推的TypeScript 操作大全系列 第 26

我推Day26 - 映射型別全攻略!讓你的 TypeScript 程式碼充滿智慧

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20241010/20124462oJZWiTEH60.jpg


TypeScript 的映射型別:基礎到實戰應用

你是否曾經需要處理過複雜的物件型別轉換?
或者在專案中管理過多變的資料結構?

TypeScript 的映射型別(Mapped Types)或許就是你的解決方案!
它們可以讓我們輕鬆地轉換型別、增加靈活性,並讓程式碼更易於維護。
今天,我們將從映射型別的基礎開始,帶你了解它在實際專案中的應用場景,並深入剖析 TypeScript 型別系統中的關鍵概念。🤓


映射型別的實際應用案例 🌟

基本的型別轉換

在專案中,我們經常需要將某個型別轉換為另一種格式。例如,假設我們有一個產品清單,其中包含產品名稱、價格和庫存狀態:

type Product = {
  name: string;
  price: number;
  inStock: boolean;
};

如果我們想將所有的產品屬性轉換成字串格式,可以使用映射型別輕鬆實現:

type ProductToString = {
  [Key in keyof Product]: string;
};

結果,我們會得到一個新型別 ProductToString,其中每個屬性都變成了字串型別:

type ProductToString = {
  name: string;
  price: string;
  inStock: string;
};

這樣的轉換非常適合用於 API 資料格式轉換,尤其是當你需要將物件的每個屬性都轉換成某種標準格式時。


動態生成 API 請求與回應的資料結構

假設我們在開發一個後端服務器 API,並且需要針對每一個請求自動生成對應的回應資料結構。
映射型別能夠根據請求的資料結構,動態生成每個欄位的回應型別,減少手動維護型別的麻煩。

type ApiRequest<T> = {
  data: T;
  success: boolean;
};

type ApiResponse<T> = {
  [Key in keyof T]: T[Key] | null;
};

在這裡,我們可以根據請求的資料結構自動生成對應的回應結構,並將每個欄位設置為可以為 null,適用於處理可能的缺失資料。

type UserRequest = { id: number; name: string };
type UserResponse = ApiResponse<UserRequest>;

// 結果型別:
// type UserResponse = {
//   id: number | null;
//   name: string | null;
// }

這樣的映射方式使得我們在面對 API 變化時,無需重複編寫相似的回應型別,大大提高了程式碼的靈活性。


深入解析 TypeScript 型別系統中的關鍵字 📚

keyofinas

  • keyof:這個運算符可以用來取得物件型別中的所有屬性名稱。它會生成這些屬性名稱的聯合型別。例如,keyof Product 會得到 'name' | 'price' | 'inStock'

  • in:用於映射型別時,可以遍歷某個型別中的所有屬性。例如,[Key in keyof Product] 會迭代 Product 的每個屬性,讓我們可以針對每個屬性進行型別轉換。

  • as:這個關鍵字可以在型別轉換時重新命名屬性。例如,如果我們想要為每個屬性加上前綴,可以這樣做:

type ProductGetters = {
  [Key in keyof Product as `get${Capitalize<string & Key>}`]: () => Product[Key];
};

// 結果型別:
// type ProductGetters = {
//   getName: () => string;
//   getPrice: () => number;
//   getInStock: () => boolean;
// }

這些關鍵字是映射型別中不可或缺的一部分,它們能夠靈活地轉換型別結構,幫助我們實現多種複雜的型別操作。


readonly? 選項

  • readonly:用於將屬性設為唯讀,避免在後續操作中誤修改它的值。
    在大型專案中,使用 readonly 能夠提升資料的安全性。

  • ?:讓屬性變為可選,在定義資料結構時可以用於處理選填欄位,減少不必要的錯誤。

這些功能在映射型別中都可以靈活地使用,例如將所有屬性設為可選或唯讀:

type OptionalProduct = {
  [Key in keyof Product]?: Product[Key];
};

type ReadonlyProduct = {
  readonly [Key in keyof Product]: Product[Key];
};

這些技巧能夠讓你的型別操作變得更加細緻和精確。


映射型別的效能考量 🚀

在大型專案中,過多使用映射型別可能會影響編譯速度。
TypeScript 需要在編譯過程中處理這些型別轉換,如果型別過於複雜,可能會導致編譯時間變長。

舉例來說,如果我們定義了一個嵌套深度很大的映射型別,可能會對 TypeScript 的型別檢查器造成負擔:

type DeepOptional<T> = {
  [Key in keyof T]?: T[Key] extends object ? DeepOptional<T[Key]> : T[Key];
};

這個型別可以遞迴地將所有屬性設為可選,但如果屬性過多且嵌套層級深,會影響編譯效能。
因此,使用這類型別時需要權衡效能和型別靈活性。


提高效能的小技巧

  • 適當使用工具型別:對於常見的型別轉換需求,可以優先考慮 TypeScript 的內建工具型別如 PartialReadonlyOmit 等,這些內建型別經過優化,性能會比自定義的映射型別更好。

  • 避免過度嵌套:對於深度嵌套的物件結構,應該儘量簡化型別設計,或者在有需要時才應用映射型別,減少不必要的型別計算。


映射型別與其他工具型別的比較 ⚖️

TypeScript 提供了許多內建的工具型別,例如 PartialPickOmit 等,它們能幫助我們更快速地進行型別轉換。但映射型別則提供了更靈活的方式,讓我們可以自定義型別的轉換邏輯。

常見工具型別與映射型別的比較

  • Partial vs 映射型別Partial 可以快速地將某個型別的所有屬性設為可選,但如果我們只想讓部分屬性變為可選,映射型別就能派上用場:
type OptionalNameProduct = {
  [Key in 'name' | 'price']?: Product[Key];
};
  • Pick vs 映射型別Pick 用於選擇某些屬性,映射型別則可以在選擇屬性的同時進行轉換:
type PickedProduct = Pick<Product, 'name' | 'price'>;

type TransformedProduct = {
  [Key in keyof Product as `transformed${Capitalize<string & Key>}`]: Product[Key];
};
  • Omit vs 映射型別Omit 可以輕鬆刪除某些屬性,而映射型別能進一步自定義過濾條件:
type ProductWithoutPrice = {
  [Key in keyof Product as Key extends 'price' ? never : Key]: Product[Key];
};

透過這些比較,可以幫助讀者更好地理解什麼時候應該使用內建工具型別,什麼時候則需要自定義的映射型別來應對複雜的需求。


重點小結:掌握映射型別的核心技巧

📌 實際應用場景
映射型別能夠輕鬆處理型別轉換,特別適合動態生成 API 回應結構,能夠大幅提升開發效率。

📌 深入理解 TypeScript 型別系統
keyofinas 等關鍵字能讓映射型別更加靈活,readonly? 則可以增強資料的安全性,讓型別操作更精確。

📌 效能考量
在大型專案中使用映射型別時,應該特別注意編譯時間和效能。適當使用 TypeScript 的內建工具型別如 PartialReadonly 等,有助於優化效能。

📌 工具型別與映射型別的比較
TypeScript 提供了豐富的工具型別,映射型別則能提供更多自定義的可能性。
透過結合兩者,可以滿足不同的開發需求,提升程式碼的可讀性和維護性。


結尾

在 TypeScript 的世界裡,映射型別讓我們得以輕鬆地操控型別,為每一行程式碼注入更多靈活性和創造力。
只要掌握這些技巧,你就能用更簡潔、更安全的方式解決開發中的複雜問題。

💡寫程式,就像解開一個個謎題,而你就是那個不斷進化的解謎高手!🚀
Happy coding! ✨


上一篇
我推Day25 - 讓 TypeScript 炸裂你的腦袋!用映射型別打造超型別安全的解析器技巧
下一篇
我推Day27 - 玩轉 TypeScript 進階映射型別,入門直接變精通
系列文
我推的TypeScript 操作大全30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言