TypeScript 中的實用型別

TypeScript 中的實用型別

本文將解釋 TypeScript 中的實用型別。

YouTube Video

TypeScript 中的實用型別

TypeScript 的實用型別是基於現有型別創建新型別的便利工具。這使型別定義更加靈活,並提高了程式碼的可重複使用性。在這裡,我們將詳細解釋常用的實用型別,並通過範例程式碼來討論如何使用每一個。

Partial<T>

Partial<T> 使物件型別的所有屬性變為可選(允許 undefined)。當您只想使用原始型別中的部分屬性時,這非常有用。

 1interface User {
 2  id: number;
 3  name: string;
 4  age: number;
 5}
 6
 7function updateUser(user: Partial<User>) {
 8  console.log(user);
 9}
10
11updateUser({ name: "Alice" }); // Updates only 'name'
  • 在上述範例中,使用 Partial<User> 使得 User 型別的所有屬性變為可選。因此,在 updateUser 函式中,您可以僅傳遞屬性的一部分。

Required<T>

Required<T> 將所有屬性(包括可選屬性)設置為必填項。當您希望將可選屬性轉換為必填屬性時,可以使用此功能。

 1interface User {
 2  id: number;
 3  name?: string;
 4  age?: number;
 5}
 6
 7function createUser(user: Required<User>) {
 8  console.log(user);
 9}
10
11// createUser({ id: 1 }); // Error: 'name' and 'age' are required
12createUser({ id: 1, name: "Alice", age: 25 });
  • 通過使用 Required<User>nameage 等屬性會被視為必填項。

Readonly<T>

Readonly<T> 將物件的所有屬性設置為唯讀。這可防止物件的值被更改。

 1interface User {
 2  id: number;
 3  name: string;
 4}
 5
 6const user: Readonly<User> = {
 7  id: 1,
 8  name: "Alice"
 9};
10
11// user.id = 2; // Error: 'id' is read-only
12console.log(user);
  • 通過使用 Readonly<T>,您可以保護物件的屬性不被更改。當您希望在開發過程中防止資料被意外修改時,這非常有效。

Record<K, T>

Record<K, T> 創建一個具有指定鍵和值型別的映射型別。K 代表鍵的型別(例如 stringnumber),T 代表值的型別。

 1type Roles = "admin" | "user" | "guest";
 2interface ReadWritePermissions {
 3  read: boolean;
 4  write: boolean;
 5}
 6
 7const rolePermissions: Record<Roles, ReadWritePermissions> = {
 8  admin: { read: true, write: true },
 9  user: { read: true, write: false },
10  guest: { read: false, write: false },
11};
12
13console.log(rolePermissions);
  • Record<K, T> 在您需要定義鍵值對時非常有用。在上面的範例中,權限是根據使用者角色定義的。

Pick<T, K>

Pick<T, K> 從物件型別中僅提取指定的屬性。您可以通過僅提取必要的屬性來創建新型別。

 1interface User {
 2  id: number;
 3  name: string;
 4  age: number;
 5}
 6
 7type UserSummary = Pick<User, "id" | "name">;
 8
 9const summary: UserSummary = {
10  id: 1,
11  name: "Alice"
12};
13
14console.log(summary);
  • 通過使用 Pick<T, K>,您可以從物件型別中提取特定屬性並將其視為新型別。例如,在上述範例中僅提取了 idname

Omit<T, K>

Omit<T, K> 用於從物件型別中排除指定的屬性。這是 Pick 的相反操作。

 1interface User {
 2  id: number;
 3  name: string;
 4  age: number;
 5  email: string;
 6}
 7
 8type UserWithoutEmail = Omit<User, "email">;
 9
10const userWithoutEmail: UserWithoutEmail = {
11  id: 1,
12  name: "Alice",
13  age: 25
14};
15
16console.log(userWithoutEmail);
  • 通過使用 Omit<T, K>,你可以透過排除指定的屬性來創建一個新的型別。在上述範例中,email 屬性被排除。

Exclude<T, U>

Exclude<T, U> 通過從聯合型別 T 中移除型別 U 來創建新的型別。當你想要移除特定型別時可以使用它。

1type Status = "active" | "inactive" | "pending";
2type ExcludedStatus = Exclude<Status, "pending">;
3
4const userStatus: ExcludedStatus = "active"; // "pending" is excluded, so it cannot be chosen
5console.log(userStatus);
  • 通過使用 Exclude<T, U>,你可以從聯合型別中移除不必要的型別。在上述範例中,由於 "pending" 被排除,僅能選擇 "active""inactive"

Extract<T, U>

Extract<T, U> 從聯合型別 T 中提取符合型別 U 的部分。當你想要僅提取特定型別時,這非常有用。

1type Status = "active" | "inactive" | "pending";
2type ActiveStatus = Extract<Status, "active" | "pending">;
3
4const userStatus: ActiveStatus = "active"; // "inactive" cannot be chosen
5console.log(userStatus);
  • Extract<T, U> 執行的是與 Exclude 相反的操作。在上述範例中,僅能選擇 "active""pending"

NonNullable<T>

NonNullable<T> 創建一個排除了 nullundefined 的型別。當你想從可選型別中排除這些值時,這會很有幫助。

1type UserName = string | null | undefined;
2type ValidUserName = NonNullable<UserName>;
3
4const userName: ValidUserName = "Alice"; // null and undefined cannot be chosen
5console.log(userName);
  • NonNullable<T> 排除了 nullundefined,確保值一定存在。

結論

TypeScript 的工具型別是使型別定義更簡潔且更靈活的強大工具。了解並適當使用像是 PartialRequiredReadonlyRecord 等基礎工具型別,可以提升程式碼的重用性與可維護性。掌握這些型別可以實現更強健且安全的型別定義,從而促進高效開發。

TypeScript 的 keyof 運算子

TypeScript 的 keyof 運算子用於取得物件型別的所有屬性名稱。使用此運算符,您可以將物件類型的鍵作為聯合類型來獲取。這對於編寫類型安全的程式碼非常有用。

基本用法

1interface Person {
2    name: string;
3    age: number;
4    email: string;
5}
6
7// Use keyof to get the property names of Person
8type PersonKeys = keyof Person; // "name" | "age" | "email"

範例用法

在函數參數中使用它

您可以使用 keyof 來定義函數,其類型基於物件的特定屬性。

 1function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
 2    return obj[key];
 3}
 4
 5const person: Person = { name: "Alice", age: 30, email: "alice@example.com" };
 6const userName = getProperty(person, "name"); // type is string
 7const age = getProperty(person, "age");   // type is number
 8
 9console.log("Name:", userName);
10console.log("Age:", age);
  • 這個函式根據指定的鍵,以型別安全的方式從物件中取得屬性。

加強類型限制

通過使用 keyof,您可以確保傳遞給函數的鍵在編譯時被驗證。

1// Passing an invalid property name results in an error
2const invalid = getProperty(person, "invalidKey"); // Error
  • 這段程式碼展示了如果指定不存在的屬性名稱,將會在編譯時出現錯誤。

總結

  • keyof 運算符用於檢索物件類型的所有屬性名稱。
  • 您可以將屬性名稱作為聯合類型獲取,從而實現類型安全的程式碼。
  • 通過在函數參數中使用它,您可以限制函數僅接受有效的屬性名稱。

通過這種方式,keyof 運算符增強了 TypeScript 中的類型安全性,幫助您編寫更穩健的程式碼。

您可以在我們的 YouTube 頻道上使用 Visual Studio Code 來跟隨上述文章一起學習。 請也查看我們的 YouTube 頻道。

YouTube Video