iT邦幫忙

2024 iThome 鐵人賽

DAY 3
0
JavaScript

TypeScript Type Challenges 冒險篇章:30 天闖關之旅,type 簡單了?你確定?系列 第 3

第3關:Pick!TypeScript 撿寶術:用 Pick 精準撿取型別

  • 分享至 

  • xImage
  •  

第3關:Pick

關卡簡介

Implement the built-in Pick<T, K> generic without using it.
Constructs a type by picking the set of properties K from T

實現內建的 Pick<T, K> 泛型,而不使用它。
通過從 T 中選擇屬性 K 的集合來構造一個型別。

任務說明:

interface Todo {
  title: string
  description: string
  completed: boolean
}

type TodoPreview = MyPick<Todo, 'title' | 'completed'>

const todo: TodoPreview = {
    title: 'Clean room',
    completed: false,
}

接下來,你的任務是讓下面的type cases測試通過:

type cases = [
  Expect<Equal<Expected1, MyPick<Todo, 'title'>>>,
  Expect<Equal<Expected2, MyPick<Todo, 'title' | 'completed'>>>,
]

interface Todo {
  title: string
  description: string
  completed: boolean
}

interface Expected1 {
  title: string
}

interface Expected2 {
  title: string
  completed: boolean
}

冒險指南:

在這一關中,我們需要:

  1. 創建一個型別,它接受兩個參數:一個型別 T 和從 T 中選擇的鍵的聯合型別 K。
  2. 最終的型別應該僅包含 T 中屬性鍵為 K 的屬性。

我們會用到:

  1. TypeScript 的「映射型別」(Mapped Types)來創建一個新的型別。
  2. 確保 K 是 T 鍵的「子集」(Subset)。

通關方式:

使用 keyof 操作符獲取 T 的所有鍵。
過濾出 K 中的鍵並構造新的型別。

type MyPick<T, K extends keyof T> = {
  [P in K]: T[P];
};

細節分析:

    • K extends keyof T:
    • Ensures that K is a union of keys from T.
    • keyof T: This operator produces a union type of all the keys of T. For example, if T is { a: number; b: string }, then keyof T is 'a' | 'b'.
    • K extends keyof T: This means that K must be a union of keys that are valid within T. If T has keys 'a' and 'b', then K can only be 'a' | 'b'. This ensures type safety by preventing any invalid keys from being used.
    • [P in K]: T[P]:
    • This part constructs a new type where each property is taken from T but only for the keys specified in K.
    • [P in K]: This is a mapped type syntax. It iterates over each key P in the union K.
    • T[P]: For each key P, it assigns the corresponding property type from T. In other words, for each key in K, the new type will have the same property type as in T.
      這樣,我們就能順利通過測試!

關鍵字補給:

  • Pick<T, K>:

    • 用途: 用於從型別 T 中選擇指定鍵 K 的屬性來構造新型別。
    • 範例:
      interface Todo {
        title: string;
        description: string;
        completed: boolean;
      }
      
      type TodoPreview = Pick<Todo, 'title' | 'completed'>;
      
      const todo: TodoPreview = {
        title: 'Clean room',
        completed: false,
      };
      
  • extends:

    • 用途: 用來表示型別的繼承或約束。它確保一個型別符合另一個型別的要求。
    • 範例:
    interface Base {
      id: number; // 基礎型別的屬性
    }
    
    interface Extended extends Base {
      name: string; // 繼承並新增屬性
    }
    
    const obj: Extended = { id: 1, name: 'Alice' };
    
  • keyof:

    • 用途: 這個操作符會產生型別 T 中所有鍵的聯合型別。
    • 範例:
      interface Todo {
        title: string;
        description: string;
        completed: boolean;
      }
      
      type TodoKeys = keyof Todo; // 'title' | 'description' | 'completed'
      
  • 聯合型別(Union of Keys):

    • 用途: 表示多個鍵的聯合型別,允許選擇其中之一或多個。
    • 範例:
      type KeyUnion = 'title' | 'completed'; // 聯合型別,可以是 'title' 或 'completed'
      
  • 映射型別(Mapped Types):

    • 用途: 根據已有型別創建新型別。使用 in 操作符來遍歷原始型別的鍵。
    • 範例:
      type MappedType<T> = {
        [K in keyof T]: T[K];
      };
      
      interface Todo {
        title: string;
        description: string;
        completed: boolean;
      }
      
      type TodoCopy = MappedType<Todo>; // 與 Todo 相同的型別
      
  • in 操作符:

    • 用途: 用於映射型別中來遍歷鍵。
    • 範例:
      type MyPick<T, K extends keyof T> = {
        [P in K]: T[P];
      };
      
      // `[P in K]` 用來遍歷 K 中的每個鍵 P
      type TodoPreview = MyPick<Todo, 'title' | 'completed'>;
      
  • Subset:

    • 用途: 表示一個型別是另一個型別的子集,確保型別的有效性和安全性。
    • 範例:
      interface Todo {
        title: string;
        description: string;
        completed: boolean;
      }
      
      // 'title' | 'completed' 是 Todo 鍵的子集
      type TodoSubset = Pick<Todo, 'title' | 'completed'>;
      

總結:

本次介紹了 Pick 的實作,許多關鍵字會在第7關進一步詳細介紹和補充更多例子!下一關會挑戰Readonly,期待再相見!


上一篇
第2關:Hello World,遇見最熟悉的陌生人
下一篇
第4關:Readonly!TypeScript 可遠觀不可褻玩焉: Readonly 保護罩
系列文
TypeScript Type Challenges 冒險篇章:30 天闖關之旅,type 簡單了?你確定?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言