Anophel-آنوفل فیلتر کردن انواع مقدار در TypeScript

فیلتر کردن انواع مقدار در TypeScript

انتشار:
1
0

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

در این آموزش، آرایه‌ای حاوی داده‌های انواع mixed را با استفاده از متد ()filter فیلتر می‌کنیم و مطمئن می‌شویم که TypeScript مقادیر را به درستی استنتاج می‌کند.

پیش نیازها
برای دنبال کردن این آموزش، شما نیاز دارید:

1.TypeScript روی سیستم شما راه اندازی شده است
2.برای یادگیری نحوه تنظیم آن، به صفحه مستندات مراجعه کنید. اگر نمی‌توانید آن را تنظیم کنید یا نمی‌خواهید، می‌توانید از زمین بازی TypeScript استفاده کنید
3.آشنایی با رابط ها و تایپ گارد در TypeScript
4.یک ویرایشگر متن خوب که می تواند خطاها را قبل از کامپایل به شما نشان دهد، مانند VS Code، که دارای پشتیبانی داخلی TypeScript است.

نحوه فیلتر کردن عناصر در TypeScript

یکی از رایج ترین وظایف در برنامه نویسی فیلتر کردن یک آرایه است. جاوا اسکریپت با متد ()filter ارائه می شود که یک آرایه را بر اساس معیارها یا شرایط داده شده فیلتر می کند و یک آرایه جدید را تنها با عناصری که شرط داده شده را پاس کرده اند برمی گرداند.

با فرض اینکه یک آرایه با اعداد دارید:

const numbers = [10, 18, 20, 30, 40];

اگر می خواهید یک آرایه جدید فقط با اعداد بزرگتر از 20 ایجاد کنید، می توانید عناصر را به صورت زیر فیلتر کنید:

onst greaterThanTwenty = numbers.filter((number) => {
  return number > 20;
});

console.log(greaterThanTwenty);
// output
[30, 40] 

متد ()filter یک callback می گیرد که بررسی می کند که آیا عددی بزرگتر از 20 است یا خیر، و اگر شرط برآورده شود، مقدار true را برمی گرداند. سپس متد آرایه‌ای را برمی‌گرداند که فقط شامل عناصری است که شرط را برآورده می‌کنند.

TypeScript می تواند نوع آرایه جدیدی را که توسط متد ()filter برگردانده شده است، زمانی که روی متغیر greaterThanTwenty در ویرایشگر خود نگه دارید یا از زمین بازی TypeScript استفاده می کنید، می توانید تایپ آن را ببینید.

در زیر مثال دیگری است که داده های پیچیده را مدیریت می کند. در آن، ما یک رابط Doctor را برای نمایش اشیایی که در آرایه Doctor هستند تعریف می کنیم. سپس از متد ()filter برای برگرداندن آبجکت هایی استفاده می کنیم که دارای یک ویژگی خاص هستند که به Cardiology تنظیم شده است:

interface Doctor {
  type: "DOCTOR";
  name: string;
  specialty: string;
}

const doctors: Doctor[] = [
  { type: "DOCTOR", name: "John Doe", specialty: "Dermatology" },
  { type: "DOCTOR", name: "Jane Williams", specialty: "Cardiology" },
];

const cardiologists = doctors.filter(
  (doctor) => doctor.specialty == "Cardiology"
);

هنگامی که ماوس را روی متغیر Cardiology  می‌چرخانیم، متوجه می‌شویم که TypeScript استنباط می‌کند که آرایه حاوی آبجکت هایی است که با رابط Doctor مطابقت دارند.

همانطور که دیدیم، TypeScript هنگام استفاده از متد ()filter بدون هیچ مشکلی می‌تواند انواع را استنباط کند - زیرا آرایه‌هایی که تا کنون به آنها نگاه کرده‌ایم حاوی عناصری از یک نوع هستند. در بخش بعدی به فیلتر کردن یک آرایه با عناصر مختلف خواهیم پرداخت.

فیلتر کردن آرایه ای از انواع عناصر مختلف در TypeScript

در این بخش، یک برنامه کوچک ایجاد می کنیم که حاوی آرایه ای از عناصر از انواع مختلف است تا مشکلاتی را که در طول استنتاج TypeScript ایجاد می شود، مشاهده کنیم.

برای شروع، دو رابط ایجاد کنید، Doctor و Nurse :

interface Doctor {
  type: "DOCTOR";
  name: string;
  specialty: string;
}

interface Nurse {
  type: "NURSE";
  name: string;
  nursingLicenseNumber: string;
}

type MedicalStaff = Doctor | Nurse;

در مثال، شما دو واسط Doctor و Nurse را برای نمایش اشیایی که در آرایه ای که به زودی تعریف خواهیم کرد، تعریف می کنید. رابط Doctor یک شی را با فیلدهای نوع، نام و تخصص نشان می دهد. رابط پرستار دارای فیلدهای نوع، نام و NursingLicenseNumber است.

برای ذخیره اشیایی که می توانند با رابط دکتر یا پرستار نمایش داده شوند، در خط آخر یک MedicalStaff از نوع union تعریف می کنیم.

سپس، یک آرایه حاوی اشیایی ایجاد کنید که با نوع union MedicalStaff مطابقت دارند:

...
const doctor1: MedicalStaff = {
  type: "DOCTOR",
  name: "John Doe",
  specialty: "Dermatology",
};
const doctor2: MedicalStaff = {
  type: "DOCTOR",
  name: "Jane Williams",
  specialty: "Cardiology",
};

const nurse1: MedicalStaff = {
  type: "NURSE",
  name: "Bob Smith",
  nursingLicenseNumber: "RN123456",
};

ما یک آرایه staffMembers ایجاد کردیم که شامل چهار شیء است. دو شیء اول با رابط دکتر و دو شیء دیگر با رابط پرستار نشان داده می شوند.

به دنبال این، اشیایی را که دارای ویژگی nursingLicenseNumber نیستند، فیلتر کنید:

...
const nurses = staffMembers.filter((staff) => "nursingLicenseNumber" in staff);
const nursingLicenseNumbers = nurses.map((nurse) => nurse.nursingLicenseNumber);
console.log(nursingLicenseNumbers);

در خط اول، تمام اشیایی را که دارای ویژگی nursingLicenseNumber نیستند، که اشیاء مربوط به رابط Doctor هستند، فیلتر می کنیم. در مرحله بعد، از متد ()map استفاده می کنیم تا فقط اعداد مجوز پرستاری را در متغیر nursingLicenseNumbers برگردانیم. سپس شما یک هشدار می بینید.

پس از بررسی دقیق، هشدار مشابه موارد زیر است:

// Error
Property 'nursingLicenseNumber' does not exist on type 'Doctor | Nurse'.
	Property 'nursingLicenseNumber' does not exist on type 'Doctor'.

این به این دلیل است که نوع استنباط شده برای متغیر nurses در  []const nurses (Doctor | Nurse) است: حتی اگر متد ()filter اشیاء را بدون nursingLicenseProperty حذف کند. بدتر از آن، اگر ماوس را روی ویژگی nursingLicenseNumbers نگه دارید، TypeScript آن را به عنوان []const nursingLicenseNumbers : any استنتاج می کند.

در موارد ایده‌آل، متغیر nurses باید به عنوان []const nurses: Nurse  . به این ترتیب، TypeScript در map()  nurse.nursingLicenseNumber را علامت گذاری نمی کند.

فیلتر کردن با استفاده از guard نوع سفارشی با گزاره نوع

تا کنون، ما یاد گرفته‌ایم که TypeScript flags nurse.nursingLicenseNumber را نشان می‌دهد زیرا این ویژگی در رابط Doctor در دسترس نیست. برای دور زدن این خطا، باید از guard نوع سفارشی با گزاره نوع استفاده کنیم.

یک guard نوع سفارشی می‌تواند تقریباً هر نوع guardی را که خودمان تعریف می‌کنیم، در مقایسه با guard های نوع دیگر، مانند typeof، که به چند نوع داخلی محدود می‌شوند، بررسی کند.

در مثال ما، یک نوع گزاره از staff is Nurse به متد ()filter به عنوان annotation نوع بازگشت صریح اضافه کنید:

const nurses = staffMembers.filter(
  (staff): staff is Nurse => "nursingLicenseNumber" in staff
);
const nursingLicenseNumbers = nurses.map((nurse) => nurse.nursingLicenseNumber);
console.log(nursingLicenseNumbers);

تایپ پردیکت staff is Nurse به TypeScript می گوید که تابع ارسال شده به متد ()filter از نوع Nurse خواهد بود.

اگر اکنون ماوس را روی متغیر nurses نگه دارید، TypeScript آن را به صورت []Nurse: استنباط می کند:

const nurses: Nurse[] = staffMembers.filter(
  (staff): staff is Nurse => "nursingLicenseNumber" in staff
);

و وقتی ماوس را روی nursingLicenseNumbers نگه دارید، TypeScript آن را به‌جای []any به‌درستی به‌عنوان []string استنتاج می‌کند:

const nursingLicenseNumbers: string[] = nurses.map((nurse) => nurse.nursingLicenseNumber);

یکی دیگر از راه های توصیه شده برای رسیدگی به این موضوع، تعریف تابع guard نوع است. یک تابع guard نوع دارای:

یک مقدار بازگشتی که به یک بولی ارزیابی می شود
یک نوع پردیکت


کد زیر از یک نوع guard تابع isStaff استفاده می کند:

const isStaff = (staff: MedicalStaff): staff is Nurse =>
  "nursingLicenseNumber" in staff;

const nurses = staffMembers.filter(isStaff);
const nursingLicenseNumbers = nurses.map((nurse) => nurse.nursingLicenseNumber);
console.log(nursingLicenseNumbers)

در مثال، تابع محافظ نوع ()isStaff را از تابع ()filter در مثال قبلی به تابع isStaff تعریف می کنید. سپس ()filter را با تابع ()isStaff به عنوان آرگومان فراخوانی می کنید.

می‌توانید از تابع ()isStaff در مکان‌های دیگری که به یک گزاره نوع مشابه نیاز دارند، دوباره استفاده کنید.

اگر می‌خواهید به ویژگی‌هایی دسترسی داشته باشید که مختص نوع MedicalStaff هستند، می‌توانید از محافظ نوع isStaff در یک عبارت if استفاده کنید:

const surgicalNurse: MedicalStaff = {
  type: "NURSE",
  name: "Jane Doe",
  nursingLicenseNumber: "RN479312",
};

if (isStaff(surgicalNurse)) {
  console.log(surgicalNurse.nursingLicenseNumber);
}

TypeScript نوع را به نوع Nurse محدود می کند. می‌توانید با نگه داشتن ماوس روی متغیر SurgicalNurse ببینید.

مشکلات مربوط به گاردهای نوع سفارشی

یک guard نوع سفارشی می تواند بسیاری از مشکلات را هنگام فیلتر کردن آرایه ای از انواع میکس برطرف کند. با این حال، این یک راه حل خطا نیست و یک مسئله دارد که باید از آن آگاه باشید تا بهترین استفاده را از آن ببرید.

مسئله این است که تایپ اسکریپت اهمیتی نمی دهد که پیاده سازی درست باشد. این می تواند به شما احساس راحتی کاذب بدهد که در حال نوشتن کد ایمن هستید.

مثال زیر را در نظر بگیرید:

const isStaff = (staff: any) : staff is Nurse => true;

const nurses = staffMembers.filter(isStaff);
const nursingLicenseNumbers = nurses.map(nurse => nurse.nursingLicenseNumber);
console.log(nursingLicenseNumbers)

تابع ()isStaff بررسی نمی کند که آیا هیچ یک از اشیاء موجود در آرایه دارای ویژگی nursingLicenseNumber است یا خیر، و با این حال TypeScript به ما هشدار نمی دهد. این ما را گمراه می کند تا باور کنیم که اجرای درست است.

این ممکن است مانند یک اشکال در TypeScript به نظر برسد، اما این یک انتخاب طراحی است که می‌تواند در مشکل TypeScript GitHub پیدا شود.

برای اطمینان از داشتن کد ایمن، باید اجرای تابع type guard را بررسی کنید تا مطمئن شوید که آنها به خوبی پیاده‌سازی شده‌اند، زیرا TypeScript راه‌حل ساخته‌شده‌ای ندارد که بتواند این مشکل را علامت‌گذاری کند.

نتیجه

در این آموزش، نحوه فیلتر کردن مقادیر در یک آرایه با استفاده از TypeScript را یاد گرفتید. ابتدا یاد گرفتید که چگونه یک آرایه را با عناصری از نوع یکسان فیلتر کنید. سپس اقدام به فیلتر کردن یک آرایه حاوی عناصری از انواع میکس می‌کنید که مسائل استنتاج را مطرح می‌کند. از آنجا، ما از یک گارد نوع سفارشی استفاده کردیم تا به TypeScript کمک کنیم تا آرایه ای از انواع میسک را در طول فیلتر کردن به درستی استنتاج کند. برای ادامه سفر TypeScript خود، از آرشیو وبلاگ ما دیدن کنید.

#TS#تایپ_اسکریپت#فیلتر#نوع_داده#filter#typeScript
نظرات ارزشمند شما :
Loading...