iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
Modern Web

TypeScript 魔法 - 喚醒你的程式碼靈感系列 第 27

Day27 - 通用又實用的型別 - Partial & Readonly

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20231012/201520474BXm1ZIhr7.png

當處理 TypeScript 中的型別時,Partialreadonly 是兩個實用的內建型別。讓我們更深入了解這兩個型別,並透過範例來說明它們的應用。

部分型別(Partial):部分修改物件

部分型別 Partial 允許我們在一個物件型別中將所有屬性設定為可選的,這樣我們可以逐步的新增屬性或修改物件的一部分,而不需要一次性定義所有的屬性。

interface CourseGoal {
  title: string;
  description: string;
  completeUntil: Date;
}

function createCourseGoal(
  title: string,
  description: string,
  date: Date
): CourseGoal {
  let courseGoal = {};
  courseGoal.title = title; // 類型 '{}' 沒有屬性 'title'
  courseGoal.description = description; // 類型 '{}' 沒有屬性 'description'
  courseGoal.completeUntil = date; // 類型 '{}' 沒有屬性 'completeUntil'
  return courseGoal; 
  // 類型 '{}' 在類型 'CourseGoal' 中缺少下列屬性: title, description, completeUntil
}

我們這樣寫雖然是常規的 JavaScript,但在 TypeScript 對於動態新增物件屬性會報錯。

讓我們改寫程式碼,使用 Partial 告訴 TypeScript 我們最終會成為一個 CourseGoal 型別的物件。

interface CourseGoal {
  title: string;
  description: string;
  completeUntil: Date;
}

function createCourseGoal(
  title: string,
  description: string,
  date: Date
): CourseGoal {
  let courseGoal: Partial<CourseGoal> = {};
  courseGoal.title = title;
  courseGoal.description = description;
  courseGoal.completeUntil = date;
  return courseGoal; // TypeScript 報錯
}

https://ithelp.ithome.com.tw/upload/images/20231012/20152047qmLKDQhxdB.png

需要注意的是,此時 return courseGoal 會報錯,因為我們 return 的是 Partial<CourseGoal> 的型別,所以我們要使用 ascourseGoal 型別斷言轉成正確的型別 CourseGoal

interface CourseGoal {
  title: string;
  description: string;
  completeUntil: Date;
}

function createCourseGoal(
  title: string,
  description: string,
  date: Date
): CourseGoal {
  let courseGoal: Partial<CourseGoal> = {};
  courseGoal.title = title;
  courseGoal.description = description;
  courseGoal.completeUntil = date;
  return courseGoal as CourseGoal;
}

唯讀型別(Readonly):確保資料不被修改

我們在介面(interfaces) 有提到唯讀屬性,當 readonly 用於介面時,表示該介面的屬性在實現該介面的類別中是唯讀的,無法在該類別中對這些屬性進行修改。而唯讀型別也有異曲同工之妙,用於確保變數、屬性或陣列在賦值後不可被修改。

readonly 用於變數或屬性:

const names: Readonly<string[]> = ['肉鬆', '傑尼龜'];
names.push('小明'); // TypeScript 報錯,因為 names 是唯讀的陣列,不允許使用 push 方法新增元素

readonly 用於介面:

interface Person {
  readonly name: string;
}

class Student implements Person {
  readonly name: string = '肉鬆';

  changeName(newName: string) {
    this.name = newName; // TypeScript 報錯,因為 'name' 為唯讀屬性,所以無法指派至 'name'
  }
}

本日重點

  1. Partial 型別允許將物件的所有屬性設定為可選的,這樣我們可以逐步新增或修改物件的部分屬性,而不需要一次性定義所有屬性;使用語法:Partial<SomeType>,其中 SomeType 是要建立部分型別的原型。
  2. Readonly 型別用於確保變數、屬性或陣列在賦值後不可被修改;使用語法:Readonly<SomeType>,其中 SomeType 是要設定為唯讀的原型。

參考


上一篇
Day26 - 泛型(Generics)下篇 - 泛型的多種姿態
下一篇
Day28 - 組織與管理程式碼的好夥伴 - Modules & Namespaces
系列文
TypeScript 魔法 - 喚醒你的程式碼靈感30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言