ไทย

สำรวจ TypeScript Partial types คุณสมบัติทรงพลังสำหรับการสร้างพร็อพเพอร์ตี้ที่ไม่บังคับ (optional) ทำให้การจัดการอ็อบเจกต์ง่ายขึ้นและเพิ่มความสามารถในการบำรุงรักษาโค้ด

การใช้งาน TypeScript Partial Types อย่างเชี่ยวชาญ: แปลงคุณสมบัติเพื่อความยืดหยุ่น

TypeScript ซึ่งเป็นส่วนขยายของ JavaScript ได้นำ static typing เข้ามาสู่โลกของการพัฒนาเว็บที่มีความไดนามิก หนึ่งในคุณสมบัติที่ทรงพลังคือ Partial type ซึ่งช่วยให้คุณสามารถสร้างไทป์ที่พร็อพเพอร์ตี้ทั้งหมดของไทป์ที่มีอยู่เดิมกลายเป็นแบบไม่บังคับ (optional) ความสามารถนี้เปิดโลกแห่งความยืดหยุ่นในการจัดการกับข้อมูล การจัดการอ็อบเจกต์ และการโต้ตอบกับ API บทความนี้จะสำรวจ Partial type อย่างลึกซึ้ง พร้อมด้วยตัวอย่างที่นำไปใช้ได้จริงและแนวทางปฏิบัติที่ดีที่สุดเพื่อนำไปใช้อย่างมีประสิทธิภาพในโปรเจกต์ TypeScript ของคุณ

TypeScript Partial Type คืออะไร?

ไทป์ Partial<T> เป็น utility type ที่มีมาให้ใน TypeScript โดยจะรับไทป์ T เป็น generic argument และส่งคืนไทป์ใหม่ที่พร็อพเพอร์ตี้ทั้งหมดของ T เป็นแบบ optional โดยพื้นฐานแล้ว มันจะเปลี่ยนทุกพร็อพเพอร์ตี้จาก required (บังคับ) เป็น optional (ไม่บังคับ) ซึ่งหมายความว่าพร็อพเพอร์ตี้เหล่านั้นไม่จำเป็นต้องมีอยู่เมื่อคุณสร้างอ็อบเจกต์ของไทป์นั้น

พิจารณาตัวอย่างต่อไปนี้:


interface User {
  id: number;
  name: string;
  email: string;
  country: string;
}

const user: User = {
  id: 123,
  name: "Alice",
  email: "alice@example.com",
  country: "USA",
};

ตอนนี้ เรามาสร้างเวอร์ชัน Partial ของไทป์ User กัน:


type PartialUser = Partial<User>;

const partialUser: PartialUser = {
  name: "Bob",
};

const anotherPartialUser: PartialUser = {
  id: 456,
  email: "bob@example.com",
};

const emptyUser: PartialUser = {}; // ถูกต้อง

ในตัวอย่างนี้ PartialUser จะมีพร็อพเพอร์ตี้เป็น id?, name?, email?, และ country? ซึ่งหมายความว่าคุณสามารถสร้างอ็อบเจกต์ของไทป์ PartialUser ด้วยการผสมผสานพร็อพเพอร์ตี้เหล่านี้แบบใดก็ได้ หรือแม้กระทั่งไม่มีเลยก็ได้ การกำหนดค่า emptyUser แสดงให้เห็นถึงประเด็นนี้ ซึ่งเน้นย้ำคุณสมบัติหลักของ Partial นั่นคือการทำให้พร็อพเพอร์ตี้ทั้งหมดเป็นแบบ optional

ทำไมถึงควรใช้ Partial Types?

Partial types มีประโยชน์ในหลายสถานการณ์:

ตัวอย่างการใช้งาน Partial Types ในทางปฏิบัติ

1. การอัปเดตโปรไฟล์ผู้ใช้

สมมติว่าคุณมีฟังก์ชันที่อัปเดตโปรไฟล์ของผู้ใช้ คุณไม่ต้องการให้ฟังก์ชันต้องรับพร็อพเพอร์ตี้ทั้งหมดของผู้ใช้ทุกครั้ง แต่ต้องการให้อัปเดตเฉพาะฟิลด์ที่ต้องการได้


interface UserProfile {
  firstName: string;
  lastName: string;
  age: number;
  country: string;
  occupation: string;
}

function updateUserProfile(userId: number, updates: Partial<UserProfile>): void {
  // จำลองการอัปเดตโปรไฟล์ผู้ใช้ในฐานข้อมูล
  console.log(`Updating user ${userId} with:`, updates);
}

updateUserProfile(1, { firstName: "David" });
updateUserProfile(2, { lastName: "Smith", age: 35 });
updateUserProfile(3, { country: "Canada", occupation: "Software Engineer" });

ในกรณีนี้ Partial<UserProfile> ช่วยให้คุณสามารถส่งเฉพาะพร็อพเพอร์ตี้ที่ต้องการอัปเดตได้โดยไม่เกิดข้อผิดพลาดทางไทป์

2. การสร้างอ็อบเจกต์สำหรับส่งคำขอ (Request) ไปยัง API

เมื่อทำการส่งคำขอไปยัง API คุณอาจมีพารามิเตอร์ที่ไม่บังคับ การใช้ Partial สามารถทำให้การสร้างอ็อบเจกต์สำหรับคำขอนั้นง่ายขึ้น


interface SearchParams {
  query: string;
  category?: string;
  location?: string;
  page?: number;
  pageSize?: number;
}

function searchItems(params: Partial<SearchParams>): void {
  // จำลองการเรียก API
  console.log("Searching with parameters:", params);
}

searchItems({ query: "laptop" });
searchItems({ query: "phone", category: "electronics" });
searchItems({ query: "book", location: "London", page: 2 });

ในที่นี้ SearchParams กำหนดพารามิเตอร์การค้นหาที่เป็นไปได้ทั้งหมด การใช้ Partial<SearchParams> ทำให้คุณสามารถสร้างอ็อบเจกต์คำขอที่มีเฉพาะพารามิเตอร์ที่จำเป็น ทำให้ฟังก์ชันมีความหลากหลายในการใช้งานมากขึ้น

3. การสร้างอ็อบเจกต์สำหรับฟอร์ม

เมื่อทำงานกับฟอร์ม โดยเฉพาะฟอร์มที่มีหลายขั้นตอน การใช้ Partial จะมีประโยชน์อย่างมาก คุณสามารถแทนข้อมูลฟอร์มด้วยอ็อบเจกต์ Partial และค่อยๆ เติมข้อมูลลงไปเมื่อผู้ใช้กรอกฟอร์ม


interface AddressForm {
  street: string;
  city: string;
  postalCode: string;
  country: string;
}

let form: Partial<AddressForm> = {};

form.street = "123 Main St";
form.city = "Anytown";
form.postalCode = "12345";
form.country = "USA";

console.log("Form data:", form);

แนวทางนี้มีประโยชน์เมื่อฟอร์มมีความซับซ้อนและผู้ใช้อาจไม่ได้กรอกข้อมูลครบทุกช่องในคราวเดียว

การใช้ Partial ร่วมกับ Utility Types อื่นๆ

Partial สามารถใช้ร่วมกับ utility types อื่นๆ ของ TypeScript เพื่อสร้างการแปลงไทป์ที่ซับซ้อนและปรับแต่งได้มากขึ้น การผสมผสานที่มีประโยชน์บางอย่าง ได้แก่:

ตัวอย่าง: การใช้ Partial ร่วมกับ Pick

สมมติว่าคุณต้องการให้พร็อพเพอร์ตี้บางตัวของ User เท่านั้นที่เป็น optional ในระหว่างการอัปเดต คุณสามารถใช้ Partial<Pick<User, 'name' | 'email'>> ได้


interface User {
  id: number;
  name: string;
  email: string;
  country: string;
}


type NameEmailUpdate = Partial<Pick<User, 'name' | 'email'>>;

const update: NameEmailUpdate = {
  name: "Charlie",
  // country ไม่ได้รับอนุญาตที่นี่ อนุญาตเฉพาะ name และ email
};

const update2: NameEmailUpdate = {
  email: "charlie@example.com"
};

แนวทางปฏิบัติที่ดีที่สุดในการใช้ Partial Types

ข้อควรพิจารณาและตัวอย่างในระดับสากล

เมื่อทำงานกับแอปพลิเคชันระดับโลก สิ่งสำคัญคือต้องพิจารณาว่า Partial types สามารถนำมาใช้อย่างมีประสิทธิภาพในภูมิภาคและบริบททางวัฒนธรรมที่แตกต่างกันได้อย่างไร

ตัวอย่าง: ฟอร์มที่อยู่ระหว่างประเทศ

รูปแบบของที่อยู่มีความแตกต่างกันอย่างมากในแต่ละประเทศ บางประเทศต้องการส่วนประกอบของที่อยู่ที่เฉพาะเจาะจง ในขณะที่บางประเทศใช้ระบบรหัสไปรษณีย์ที่แตกต่างกัน การใช้ Partial สามารถรองรับความแตกต่างเหล่านี้ได้


interface InternationalAddress {
  streetAddress: string;
  apartmentNumber?: string; // ไม่บังคับในบางประเทศ
  city: string;
  region?: string; // จังหวัด, รัฐ ฯลฯ
  postalCode: string;
  country: string;
  addressFormat?: string; // เพื่อระบุรูปแบบการแสดงผลตามประเทศ
}


function formatAddress(address: InternationalAddress): string {
  let formattedAddress = "";

  switch (address.addressFormat) {
    case "UK":
      formattedAddress = `${address.streetAddress}\n${address.city}\n${address.postalCode}\n${address.country}`;
      break;
    case "USA":
      formattedAddress = `${address.streetAddress}\n${address.city}, ${address.region} ${address.postalCode}\n${address.country}`;
      break;
    case "Japan":
      formattedAddress = `${address.postalCode}\n${address.region}${address.city}\n${address.streetAddress}\n${address.country}`;
      break;
    default:
      formattedAddress = `${address.streetAddress}\n${address.city}\n${address.postalCode}\n${address.country}`;
  }
  return formattedAddress;
}

const ukAddress: Partial<InternationalAddress> = {
  streetAddress: "10 Downing Street",
  city: "London",
  postalCode: "SW1A 2AA",
  country: "United Kingdom",
  addressFormat: "UK"
};

const usaAddress: Partial<InternationalAddress> = {
    streetAddress: "1600 Pennsylvania Avenue NW",
    city: "Washington",
    region: "DC",
    postalCode: "20500",
    country: "USA",
    addressFormat: "USA"
};

console.log("UK Address:\n", formatAddress(ukAddress as InternationalAddress));
console.log("USA Address:\n", formatAddress(usaAddress as InternationalAddress));

interface InternationalAddress อนุญาตให้มีฟิลด์ที่ไม่บังคับ เช่น apartmentNumber และ region เพื่อรองรับรูปแบบที่อยู่ที่แตกต่างกันทั่วโลก ฟิลด์ addressFormat สามารถใช้เพื่อปรับแต่งวิธีการแสดงที่อยู่ตามแต่ละประเทศได้

ตัวอย่าง: การตั้งค่าผู้ใช้ในภูมิภาคต่างๆ

การตั้งค่าของผู้ใช้สามารถแตกต่างกันไปในแต่ละภูมิภาค การตั้งค่าบางอย่างอาจเกี่ยวข้องเฉพาะในบางประเทศหรือวัฒนธรรมเท่านั้น


interface UserPreferences {
  darkMode: boolean;
  language: string;
  currency: string;
  timeZone: string;
  pushNotificationsEnabled: boolean;
  smsNotificationsEnabled?: boolean; // ไม่บังคับในบางภูมิภาค
  marketingEmailsEnabled?: boolean;
  regionSpecificPreference?: any; // การตั้งค่าเฉพาะภูมิภาคที่ยืดหยุ่น
}

function updateUserPreferences(userId: number, preferences: Partial<UserPreferences>): void {
  // จำลองการอัปเดตการตั้งค่าผู้ใช้ในฐานข้อมูล
  console.log(`Updating preferences for user ${userId}:`, preferences);
}


updateUserPreferences(1, {
    darkMode: true,
    language: "en-US",
    currency: "USD",
    timeZone: "America/Los_Angeles"
});


updateUserPreferences(2, {
  darkMode: false,
  language: "fr-CA",
  currency: "CAD",
  timeZone: "America/Toronto",
  smsNotificationsEnabled: true // เปิดใช้งานในแคนาดา
});

interface UserPreferences ใช้พร็อพเพอร์ตี้ที่ไม่บังคับ เช่น smsNotificationsEnabled และ marketingEmailsEnabled ซึ่งอาจมีความเกี่ยวข้องเฉพาะในบางภูมิภาคเท่านั้น ฟิลด์ regionSpecificPreference ให้ความยืดหยุ่นเพิ่มเติมสำหรับการเพิ่มการตั้งค่าเฉพาะภูมิภาค

สรุป

Partial type ของ TypeScript เป็นเครื่องมืออเนกประสงค์สำหรับการสร้างโค้ดที่ยืดหยุ่นและบำรุงรักษาง่าย ด้วยการอนุญาตให้คุณกำหนดพร็อพเพอร์ตี้ที่ไม่บังคับ มันช่วยลดความซับซ้อนในการจัดการอ็อบเจกต์ การโต้ตอบกับ API และการจัดการข้อมูล การทำความเข้าใจวิธีใช้ Partial อย่างมีประสิทธิภาพ ร่วมกับการผสมผสานกับ utility types อื่นๆ สามารถเพิ่มประสิทธิภาพเวิร์กโฟลว์การพัฒนา TypeScript ของคุณได้อย่างมาก อย่าลืมใช้อย่างรอบคอบ จัดทำเอกสารวัตถุประสงค์ให้ชัดเจน และตรวจสอบข้อมูลเพื่อหลีกเลี่ยงข้อผิดพลาดที่อาจเกิดขึ้น เมื่อพัฒนาแอปพลิเคชันระดับโลก ให้พิจารณาความต้องการที่หลากหลายของภูมิภาคและวัฒนธรรมต่างๆ เพื่อใช้ประโยชน์จาก Partial types สำหรับโซลูชันที่ปรับเปลี่ยนได้และเป็นมิตรกับผู้ใช้ การใช้งาน Partial types อย่างเชี่ยวชาญจะช่วยให้คุณสามารถเขียนโค้ด TypeScript ที่แข็งแกร่ง ปรับเปลี่ยนได้ และบำรุงรักษาง่าย ซึ่งสามารถจัดการกับสถานการณ์ที่หลากหลายได้อย่างสง่างามและแม่นยำ