برنامه نویسی

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

نوشته استنلی اولیلی✏️

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

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

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

پرش به جلو:

پیش نیازها

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

  • TypeScript روی سیستم شما راه اندازی شده است
  • آشنایی با رابط ها و تایپ گارد در TypeScript
  • یک ویرایشگر متن خوب که می تواند خطاها را قبل از کامپایل به شما نشان دهد، مانند VS Code، که دارای پشتیبانی داخلی TypeScript است.

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

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

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

const numbers = [10, 15, 20, 30, 40];
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

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

console.log(greaterThanTwenty);
// output
[30, 40] 
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

TypeScript می تواند نوع آرایه جدید را که توسط the بازگردانده شده است استنتاج کند filter() روش زمانی که ماوس را بر روی greaterThanTwenty متغیر در ویرایشگر خود یا با استفاده از زمین بازی TypeScript: TypeScript متغیر را به صورت یک عدد استنباط می کند در زیر مثال دیگری است که داده های پیچیده را مدیریت می کند. در آن الف را تعریف می کنیم Doctor رابط برای نشان دادن اشیایی که در doctors آرایه. سپس از filter() روشی برای برگرداندن اشیایی که دارای a specialty ویژگی تنظیم شده به 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"
);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هنگامی که ماوس را بر روی cardiologists متغیر، متوجه خواهیم شد که 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 رابط نشان دهنده یک شی با type، name، و specialty زمینه های؛ را Nurse رابط دارای فیلدهایی است type، name، و nursingLicenseNumber.

برای ذخیره اشیایی که می توانند با هر یک از آنها نمایش داده شوند Doctor یا Nurse رابط، ما یک نوع اتحادیه تعریف می کنیم MedicalStaff در خط آخر

در مرحله بعد، یک آرایه حاوی اشیایی که با نوع اتحادیه مطابقت دارند ایجاد کنید 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",
};
const nurse2: MedicalStaff = {
  type: "NURSE",
  name: "Alice Johnson",
  nursingLicenseNumber: "RN654321",
};

const staffMembers = [doctor1, doctor2, nurse1, nurse2];
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

پس از این، اشیایی را که فاقد آن هستند فیلتر کنید nursingLicenseNumber ویژگی:

...
const nurses = staffMembers.filter((staff) => "nursingLicenseNumber" in staff);
const nursingLicenseNumbers = nurses.map((nurse) => nurse.nursingLicenseNumber);
console.log(nursingLicenseNumbers);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

پس از نوشتن کد، هشداری را مشاهده خواهید کرد: اسکرین شات از ویژگی هشدار TypeScript nursingLicenseNumber پس از بررسی دقیق، هشدار مشابه موارد زیر است:

// 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 پرچم گذاری نمی کند nurse.nursingLicenseNumber در map() روش.

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

تا اینجا پرچم های TypeScript را یاد گرفته ایم nurse.nursingLicenseNumber زیرا ملک در دسترس نیست Doctor رابط. برای دور زدن این خطا، باید از محافظ نوع سفارشی با گزاره نوع استفاده کنیم.

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

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

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 آن را به درستی استنتاج می کند string[] بجای any[]:

const nursingLicenseNumbers: string[] = nurses.map((nurse) => nurse.nursingLicenseNumber);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

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

کد زیر از a استفاده می کند 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 گارد را در an if بیانیه:

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

if (isStaff(surgicalNurse)) {
  console.log(surgicalNurse.nursingLicenseNumber);
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

TypeScript نوع را به مقدار محدود می کند Nurse نوع می‌توانید با نگه داشتن ماوس روی آن تأیید کنید surgicalNurse متغیر: ماوس را روی متغیر surgicalNurse نگه دارید تا نوع باریک شدن را تأیید کنید

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

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

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

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

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

const nurses = staffMembers.filter(isStaff);
const nursingLicenseNumbers = nurses.map(nurse => nurse.nursingLicenseNumber);
console.log(nursingLicenseNumbers)
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

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

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

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

نتیجه

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


با ردیابی خطای Typescript مدرن LogRocket در چند دقیقه راه‌اندازی کنید:

1. برای دریافت شناسه برنامه به https://logrocket.com/signup/ مراجعه کنید.
2. LogRocket را از طریق NPM یا تگ اسکریپت نصب کنید. LogRocket.init() باید سمت مشتری نامیده شود نه سمت سرور.

NPM:

$ npm i --save logrocket 

// Code:

import LogRocket from 'logrocket'; 
LogRocket.init('app/id');
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برچسب اسکریپت:

Add to your HTML:

<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

3. (اختیاری) پلاگین ها را برای ادغام عمیق تر با پشته خود نصب کنید:

  • میان افزار Redux
  • میان افزار ngrx
  • افزونه Vuex

در حال حاضر آغاز شده است

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا