فیلتر کردن انواع مقدار 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: در زیر مثال دیگری است که داده های پیچیده را مدیریت می کند. در آن الف را تعریف می کنیم
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
رابط: همانطور که دیدیم، تایپ اسکریپت می تواند انواع را در هنگام استفاده از آن استنتاج کند
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
متغیر.
پس از نوشتن کد، هشداری را مشاهده خواهید کرد: پس از بررسی دقیق، هشدار مشابه موارد زیر است:
// 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
متغیر:
مشکلات مربوط به گاردهای نوع سفارشی
یک محافظ نوع سفارشی می تواند بسیاری از مشکلات را هنگام فیلتر کردن آرایه ای از انواع مختلط برطرف کند. با این حال، این یک راه حل خطا نیست و یک مسئله دارد که باید از آن آگاه باشید تا بهترین استفاده را از آن ببرید.
مسئله این است که تایپ اسکریپت اهمیتی نمی دهد که پیاده سازی درست باشد. این می تواند به شما احساس راحتی کاذب بدهد که در حال نوشتن کد ایمن هستید.
مثال زیر را در نظر بگیرید:
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
در حال حاضر آغاز شده است