گارد نوع تعریف شده توسط کاربر در تایپ اسکریپت – از صفر تا صد


در این مقاله با روش استفاده از کارکردهای قدرتمند تایپ اسکریپت برای بهبود مدیریت نوع در اپلیکیشنها آشنا میشویم. «گاردهای نوع» (Type Guards) یکی از ویژگیهای کلیدی کدِ دارای امنیت نوع محسوب میشوند. با استفاده از گاردهای نوع میتوانیم نوع یک شیء را درون یک بلوک شرطی محدود کنیم. در این مقاله با گارد نوع تعریف شده توسط کاربر در تایپ اسکریپت آشنا خواهیم شد.
مستندات تایپ اسکریپت گارد نوع را چنین تعریف کردهاند:
نوعی از عبارت که یک بررسی زمان اجرا انجام میدهد و نوع را در یک دامنه تضمین میکند.
مهمترین بخش این توصیف آن است که گاردهای نوع در واقع شکلی از بررسی زمان اجرا هستند. معنی این گفته آن است که متغیر از نوع مورد انتظار در لحظه اجرای کد مورد بررسی قرار میگیرد. بدین ترتیب به جای استفاده از کلیدواژه any برای الزام کامپایلر تایپ اسکریپت به توقف دخالت در مورد یک مشخصه نامعلوم، استفاده از گاردهای نوع بسیار خواناتر است. گاردهای نوع بررسیهای نوع را در کد اپلیکیشن غیرفعال نمیکنند و از این رو امکان بروز خطا در آن کمتر میشود. بدین ترتیب کد اجرا میشود و تستها پاس میشوند. در این وضعیت هم کامپایلر و هم شما راضی هستید.
تایپ اسکریپت دارای گاردهای نوع درونی مانند typeof ،instanceof ،in و گاردهای نوع لفظی است. این موارد بسیار مفید هستند، اما دارای دامنه محدودی در توسعه وب مدرن هستند.
استفاده از instanceof
از instanceof میتوان برای بررسی این که آیا یک متغیر وهلهای از یک کلاس مفروض است یا نه استفاده کرد. سمت راست عملگر instanceof باید یک تابع سازنده باشد:
کد فوق خروجی زیر را در کنسول پرینت میکند:
woof meow
کامپایلر تایپ اسکریپت بلوکهای if-else را به روش مشابهی مدیریت میکند. برای نمونه نوع متغیر را در صورتی که وهلهای از Dog نباشد به Cat محدود میکند:
استفاده از typeof
از typeof در مواردی استفاده میکنیم که لازم باشد بین انواع number ،string ،boolean ،bigint ،object ،function ،symbol و undefined تمایز قائل شویم. زمانی که از ثابتهای رشتهای دیگری استفاده کنید، عملگر typeof خطایی نخواهد داشت، اما مطابق انتظار هم عمل نمیکند و در نتیجه باگهایی بروز مییابند که ردگیری آنها دشوار است. این نوع از عبارتها به صورت گاردهای نوع شناسایی نمیشوند. typeof برخلاف instanceof با یک متغیر از نوع any نیز کار میکند. در مثال زیر foo بدون هیچ اشکالی میتواند از نوع number | string باشد:
کد فوق خروجی زیر را تولید میکند:
123 not a number: foo
بخش پیچیده این است که typeof تنها بررسی نوع سطحی اجرا میکند. یعنی میتواند یک متغیر که شیء ژنریک است را تعیین کند، اما نمیتواند شکل شیء را مشخص سازد. به عنوان مثال کد زیر کار نمیکند:
if (typeof foo === 'Dog')
استفاده از in
عملگر in یک بررسی امنیتی برای وجود یک مشخصه روی یک شیء از نوع union اجرا میکند. در چنین حالتی شاخه if به انواعی محدود میشود که مشخصه مورد نظر را به صورت optional یا required دارند.
به مثال زیر توجه کنید:
استفاده از گاردهای نوع لفظی (Literal)
علاوه بر گاردهای قبلی میتوانید از ===، ==، ==! و =! برای تمییز بین مقادیر لفظی و از این رو از گاردهای نوع ساده مانند مثال زیر استفاده کنید:
این کد حتی در مثالهای پیچیده نیز مانند مواردی که از انواع لفظی در یک union استفاده میکنید، کار میکند. بدین ترتیب میتوانید مقدار یک نام مشخصه مشترک را بررسی کنید تا union را مشخص سازید. به مثال زیر توجه کنید:
کامپایلر تایپ اسکریپت به قدر کافی هوشمند است تا هر دو مورد null و undefined را با بررسیهای null == و null != کنار بگذارد. به مثال زیر توجه کنید:
استفاده از گاردهای نوع تعریف شده توسط کاربر
در پروژههای واقعی ممکن است لازم باشد گاردهای نوع تعریف شده خودمان را نیز با منطق سفارشی اعلان کنیم تا به کامپایلر تایپ اسکریپت کمک کنیم نوع را تشخیص دهد. به این منظور باید با استفاده از هر نوع منطقی که دوست دارید، تابعی اعلان کنید که به عنوان گارد نوع عمل کند. این تابع یعنی «تابع گارد نوع تعریف شده کاربر» تابعی است که یک «پیشبین نوع» (type predicate) به شکل event is MouseEvent به جای یک نوع بازگشتی بازمیگرداند:
اگر تابع مقدار true بازگشت دهد، تایپ اسکریپت نوع MouseEvent را در هر بلوک مورد حفاظت از سوی یک فراخوانی به تابع محدود میسازد. به بیان دیگر نوع دقیقتر خواهد بود. event is MouseEvent کامپایلر را مطمئن میسازد که event ارسالی به گارد نوع واقعاً یک MouseEvent است. به مثال زیر توجه کنید:
از پیشبین نوع تابع گارد (test is Dog در موقعیت نوع بازگشتی تابع) در زمان کامپایل برای محدودسازی انواع استفاده میشود، در حالی که تابع در زمان اجرا استفاده میشود. پیشبین نوع و تابع باید با هم توافق داشته باشد تا کد کار کند. تابعهای گارد نوع الزاماً از typeof یا instanceof استفاده نمیکنند و میتوانند از منطق پیچیدهتری بهره بگیرند. برای نمونه کد زیر مشخصه شیء را برای تعیین این که یک Dog است یا نه بررسی میکند:
جمعبندی
گاردهای نوع به عنوان یکی از ویژگیهای کمتر شناختهشده تایپ اسکریپت بری محدودسازی انواع و کسب رضایت کامپایلر بسیار مفید هستند. آنها به حفظ امنیت نوع کمک میکنند و موجب میشوند که کد نوشتهشده سادهتر درک شده و نگهداری آسانتری داشته باشد. گاردهای نوع داخلی مانند typeof و instanceof وجود دارند، اما کاربرد آنها محدود است. گاردهای نوع تعریف شده از سوی کاربر میتوانند با پیشبین نوع سفارشی و یک مشخصه یکتا از نوع مطلوب تعریف شوند. برای ایجاد یک گارد نوع سفارشی باید مراحل زیر را طی کنید:
- تابعی بنویسید که به جای نوع بازگشتی یک پیشبین نوع مانند event is MouseEvent داشته باشد.
- منطقی را پیادهسازی کنید که نوع متغیر ارسالی را به صورت پارامتری که از typeof ،instanceof یا هر نوع عملگر دیگر تابع که مقدار بولی به دست میدهد، تعیین کند.
از گاردهای نوع استفاده کنید تا قدرت کامپایلر تایپ اسکریپت موجب خواناتر شدن کد شما شده و احتمال بروز خط در آن را کاهش دهد.
اگر این مطلب برای شما، مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- مجموعه آموزشهای برنامهنویسی
- مفهوم تابع در تایپ اسکریپت — به زبان ساده
- راهنمای جامع تایپ اسکریپت (Typescript) — از صفر تا صد
- درک انواع در تایپ اسکریپت — به زبان ساده
==