گزاره های نوع در TypeScript چیست؟ با مثال کد توضیح داده شده است
محمولات نوع یک ویژگی نحوی جالب در TypeScript است. در حالی که آنها در همان مکان حاشیه نویسی نوع برگشتی ظاهر می شوند، بیشتر شبیه جملات تاییدی کوتاه هستند تا حاشیه نویسی های معمولی. این به شما کنترل بیشتری بر تحلیل نوع می دهد.
با انتشار TypeScript 5.5، کار با محمولات نوع در حال حاضر بصری تر شده است زیرا می تواند در بسیاری از موارد به طور خودکار آنها را استنتاج کند. اما اگر در حال پیمایش مبانی کد کمی قدیمیتر هستید، احتمالاً بیشتر با محمولات دستنویس مواجه میشوید.
در این مقاله، به طور خلاصه تحلیل خواهیم کرد که محمولات چه نوع هستند و چرا مفید هستند. بیایید با تحلیل مشکلی که آنها حل می کنند شروع کنیم.
مشکل
به اعتقاد من بهترین راه برای درک مفید بودن محمولات نوع، توجه به مشکلاتی است که در صورت نداشتن آنها به وجود می آیند:
function isString ( value: unknown ): boolean { return typeof value === "string" ; } function padLeft ( padding: number | string , input: string ) { if (isString(padding)) { return padding + input; // ^ // string | number } return " " .repeat(padding) + input; // Opps type error here // ^ // string | number }
در اینجا، نوع برگشتی isString
روی boolean
تنظیم شده است، و ما از آن در تابعی به نام padLeft
برای اضافه کردن padding به سمت چپ یک رشته ورودی استفاده میکنیم. padding
می تواند یک رشته داده شده یا تعداد مشخصی از کاراکترهای فاصله باشد.
ممکن است تعجب کنید که چرا من نوع بازگشتی را به صورت boolean
کدگذاری کردم. این برای نشان دادن مشکل است. اگر هیچ گونه حاشیه نویسی نوع برگشتی اضافه نکنید و از آخرین نسخه TypeScript استفاده کنید، در اینجا متوجه مشکلی نخواهید شد. در حال حاضر، من را تحمل کنید - به زودی در مورد تفاوت های مربوط به نسخه بحث خواهیم کرد.
این تابع در زمان اجرا به راحتی کار می کند، اما TypeScript نمی تواند هر نوع باریک کردن را با isString
انجام دهد. در نتیجه نوع padding
string | number
هم در داخل و هم خارج از دستور if
. این منجر به تضاد با انتظار repeat
برای اولین آرگومان می شود و باعث خطای نوع می شود.
راه حل: Predicates نوع را وارد کنید
حتی اگر با اصطلاح محمول ناآشنا باشید، احتمالاً قبلاً از آنها استفاده کرده اید. محمول ها در برنامه نویسی به سادگی توابعی هستند که برای پاسخ دادن به سوال بله/خیر، یک بولی برمی گرداند. چندین روش آرایه داخلی جاوا اسکریپت، مانند filter
, find
, every
, و some
گزاره ها برای کمک به تصمیم گیری استفاده می کنند.
محمولات نوع راهی برای مفیدتر کردن گزاره ها برای باریک کردن نوع هستند. ما می توانیم با استفاده از یک گزاره نوع به عنوان نوع برگشتی مشکل را حل کنیم:
function isString ( value: unknown ): value is string { return typeof value === "string" ; }
در اینجا گزاره نوع value is string
. سه چیز می گوید:
تابع یک محمول است. پس اگر بخواهید چیزی غیر از مقدار Boolean را برگردانید TypeScript یک خطا نشان می دهد.
اگر true
را برگرداند، value
از نوع string است.
اگر false
برگرداند، value
از نوع رشته نیست.
گزارههای نوع به شما امکان میدهند محافظهای نوع تعریفشده توسط کاربر ایجاد کنید. محافظهای تایپ چکهای منطقی هستند که به شما امکان میدهند انواع را به انواع خاصتر اصلاح کنید، یا آنها را محدود کنید. پس ، تابع فوق نیز یک محافظ نوع تعریف شده توسط کاربر است.
اینم کد کامل:
function isString ( value: unknown ): value is string { return typeof value === "string" ; } function padLeft ( padding: number | string , input: string ) { if (isString(padding)) { return padding + input; // ^ // string } return " " .repeat(padding) + input; // ^ // number }
در اینجا TypeScript به درستی نوع padding
در داخل دستور if
و خارج از آن محدود می کند.
حال اجازه دهید به طور خلاصه به نحوه کار گزاره های نوع قبل از TypeScript 5.5 و بهبود این نسخه نگاه کنیم.
گزاره ها را قبل از TypeScript 5.5 تایپ کنید
در مثال قبلی، اگر هیچ نوع بازگشتی را مشخص نکنیم، به صورت boolean
استنباط میشود:
function isString ( value: unknown ) { return typeof value === "string" ; } function padLeft ( padding: number | string , input: string ) { if (isString(padding)) { return padding + input; // ^ // string | number } return " " .repeat(padding) + input; // Opps type error here // ^ // string | number }
در نتیجه، همان خطای boolean
را داریم که به صورت دستی نوع بازگشتی را نوشتیم. در اینجا پیوند زمین بازی TypeScript برای قطعه کد بالا آمده است . برو و توابع یا متغیرها را شناور کن تا حس بهتری نسبت به انواع داشته باشد. سپس ببینید چگونه نوشتن گزاره نوع مشکل را حل می کند.
اگر گزاره نوع را مشخص نکنیم، استفاده از روشهایی مانند filter
نیز میتواند منجر به تشخیص نوع نادرست شود:
function isString ( value: unknown ) { return typeof value === "string" ; } const numsOrStrings = [ 1 , 'hello' , 2 , 'world' ]; // ^ // strings: (string | number)[] const strings = numsOrStrings.filter(isString); // ^ // strings: (string | number)[]
حال بیایید ببینیم که چگونه TypeScript 5.5 وضعیت را بهبود می بخشد.
محمولات را بعد از TypeScript 5.5 تایپ کنید
یکی از آپشن های برتر TypeScript 5.5 این است که میتواند محمولات نوع را با تجزیه و تحلیل بدنه تابع استنتاج کند. پس ، اگر از TypeScript نسخه 5.5 یا بالاتر استفاده می کنید، لازم نیست گزاره نوع را به عنوان نوع برگشتی isString
بنویسید. TypeScript این کار را برای شما انجام می دهد و کدی مانند آنچه در مثال زیر مشاهده می کنید کاملاً خوب کار می کند:
function isString ( value: unknown ) { return typeof value === "string" ; } function padLeft ( padding: number | string , input: string ) { if (isString(padding)) { return padding + input; // ^ // string } return " " .repeat(padding) + input; // Opps type error here // ^ // number } const numsOrStrings = [ 1 , 'hello' , 2 , 'world' ]; const strings = numsOrStrings.filter(isString); // ^ // strings: string[] const numbers = numsOrStrings.filter( ( v ) => !isString(v)); // ^ // numbers: number[]
من هنوز موقعیتی پیدا نکرده ام که از استنتاج خودکار محمولات نوع ناراضی باشم. اگر یکی را پیدا کردید، همیشه می توانید خودتان را به صورت دستی بنویسید.
مطالعه بیشتر
در این مقاله به اختصار به تحلیل گزاره های نوع در TypeScript پرداختیم. اگر علاقه مند به یادگیری بیشتر و درک موارد لبه هستید، در اینجا راهنمای رسمی وجود دارد:
چه جدید است → TypeScript 5.5 → Predicates نوع استنتاجی
کتاب راهنما ← محدود کردن ← استفاده از محمولات نوع
با تشکر برای خواندن! دفعه بعد می بینمت!
پس زمینه عکس روی جلد از Mona Eendra در Unsplash است
ارسال نظر