فارسی

با تایپ‌های Partial در TypeScript، یک ویژگی قدرتمند برای ایجاد خصوصیات اختیاری، ساده‌سازی کار با اشیاء و بهبود نگهداری کد با مثال‌های عملی و بهترین شیوه‌ها آشنا شوید.

تسلط بر تایپ‌های Partial در TypeScript: تبدیل خصوصیات برای انعطاف‌پذیری

TypeScript، به عنوان یک بالامجموعه از جاوااسکریپت، تایپ‌دهی استاتیک را به دنیای پویای توسعه وب می‌آورد. یکی از ویژگی‌های قدرتمند آن، تایپ Partial است که به شما امکان می‌دهد یک تایپ جدید بسازید که در آن تمام خصوصیات یک تایپ موجود اختیاری هستند. این قابلیت، دنیایی از انعطاف‌پذیری را هنگام کار با داده‌ها، دستکاری اشیاء و تعاملات API باز می‌کند. این مقاله به طور عمیق به بررسی تایپ Partial می‌پردازد و مثال‌های عملی و بهترین شیوه‌ها را برای استفاده مؤثر از آن در پروژه‌های TypeScript شما ارائه می‌دهد.

تایپ Partial در TypeScript چیست؟

تایپ Partial<T> یک تایپ کاربردی داخلی (utility type) در TypeScript است. این تایپ یک تایپ T را به عنوان آرگومان جنریک خود می‌گیرد و یک تایپ جدید برمی‌گرداند که در آن تمام خصوصیات 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 را برجسته می‌کند: این تایپ تمام خصوصیات را اختیاری می‌کند.

چرا از تایپ‌های Partial استفاده کنیم؟

تایپ‌های Partial در چندین سناریو ارزشمند هستند:

مثال‌های عملی از تایپ‌های Partial

۱. به‌روزرسانی پروفایل کاربر

تصور کنید تابعی دارید که پروفایل یک کاربر را به‌روزرسانی می‌کند. شما نمی‌خواهید این تابع هر بار مجبور به دریافت تمام خصوصیات کاربر باشد؛ در عوض، می‌خواهید اجازه دهید فیلدهای خاصی به‌روز شوند.


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> به شما اجازه می‌دهد فقط خصوصیاتی را که نیاز به به‌روزرسانی دارند، بدون ایجاد خطاهای تایپ، ارسال کنید.

۲. ساختن یک شیء درخواست برای 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>، می‌توانید اشیاء درخواست را فقط با پارامترهای ضروری ایجاد کنید و تابع را کاربردی‌تر سازید.

۳. ایجاد یک شیء فرم

هنگام کار با فرم‌ها، به ویژه فرم‌های چند مرحله‌ای، استفاده از 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 با دیگر تایپ‌های کاربردی

Partial را می‌توان با دیگر تایپ‌های کاربردی TypeScript ترکیب کرد تا تبدیلات تایپ پیچیده‌تر و سفارشی‌تری ایجاد شود. برخی از ترکیبات مفید عبارتند از:

مثال: Partial با Pick

فرض کنید می‌خواهید فقط خصوصیات خاصی از User در حین به‌روزرسانی اختیاری باشند. می‌توانید از 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

ملاحظات و مثال‌های جهانی

هنگام کار با برنامه‌های جهانی، ضروری است که در نظر بگیرید چگونه تایپ‌های Partial می‌توانند به طور مؤثر در مناطق و زمینه‌های فرهنگی مختلف استفاده شوند.

مثال: فرم‌های آدرس بین‌المللی

فرمت‌های آدرس در کشورهای مختلف به طور قابل توجهی متفاوت است. برخی کشورها به اجزای آدرس خاصی نیاز دارند، در حالی که برخی دیگر از سیستم‌های کد پستی متفاوتی استفاده می‌کنند. استفاده از 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));

اینترفیس 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 // در کانادا فعال است
});

اینترفیس UserPreferences از خصوصیات اختیاری مانند smsNotificationsEnabled و marketingEmailsEnabled استفاده می‌کند که ممکن است فقط در مناطق خاصی مرتبط باشند. فیلد regionSpecificPreference انعطاف‌پذیری بیشتری برای افزودن تنظیمات مختص منطقه فراهم می‌کند.

نتیجه‌گیری

تایپ Partial در TypeScript ابزاری همه‌کاره برای ایجاد کدی انعطاف‌پذیر و قابل نگهداری است. با اجازه دادن به تعریف خصوصیات اختیاری، دستکاری اشیاء، تعاملات API و مدیریت داده‌ها را ساده می‌کند. درک نحوه استفاده مؤثر از Partial، همراه با ترکیبات آن با سایر تایپ‌های کاربردی، می‌تواند به طور قابل توجهی گردش کار توسعه TypeScript شما را بهبود بخشد. به یاد داشته باشید که از آن با احتیاط استفاده کنید، هدف آن را به وضوح مستند کنید و داده‌ها را برای جلوگیری از مشکلات احتمالی اعتبارسنجی کنید. هنگام توسعه برنامه‌های جهانی، نیازهای متنوع مناطق و فرهنگ‌های مختلف را در نظر بگیرید تا از تایپ‌های Partial برای راه‌حل‌های سازگار و کاربرپسند بهره‌برداری کنید. با تسلط بر تایپ‌های Partial، می‌توانید کدی قوی‌تر، سازگارتر و قابل نگهداری‌تر در TypeScript بنویسید که بتواند با ظرافت و دقت، انواع سناریوها را مدیریت کند.