سلام دوستان! توی تایپاسکریپت یه ویژگی داریم به اسم Type Predicate که هدف اون بهبود Type Narrowing هست. ابتدا با معنی Narrowing آشنا بشیم:
Narrowing چیه؟ 🤔
معنی واژه Narrowing یعنی محدود کردن یا باریک کردن. تایپاسکریپت با عملیات Narrowing کاری میکنه که نوعِ یک مقدار به شکل خاصتر و مشخصتر برای ما در دسترس باشه.
توی عکس همونطور که میبینیم، پارامتر x ممکنه رشته باشه یا عدد:

توی این کد دو عملیات Narrowing انجام گرفته: یکی برای بلاک if و یکی هم برای else. با این ویژگی، با پارامتر x توی بلاک if فقط به صورت رشته رفتار میشه. برای مثال اگه متد toFixed رو صدا بزنیم خطا میگیریم. چون توی این بلاک، x فقط به صورت رشته قابل دسترس هست. همچنین توی بلاک else تایپاسکریپت میدونه که نوع x دیگه رشته نیست و قطعاً عددی هست. پس با اون مثل یک عدد رفتار میکنه.
خب حالا بریم که موضوع اصلی این پست رو بررسی کنیم. توی تایپاسکریپت اگه چنین کدی داشته باشیم:
function isString(value: any) { return typeof value === 'string'; } const value = Math.random() < 0.5 ? "string" : 10; if (isString(value)) { console.log('value is a string', <<value.length>>); } else { console.log('value is not a string', value); }
کامپایلر تایپاسکریپت توی خط ۹ بهمون خطا میده که:
Property 'length' does not exist on type '"string" | 10'
برای اجرای این کد میتونین رو ببینین. این خطا به این معنی هست که تایپاسکریپت توی خط ۹ نتونسته نوع متغیر value رو تشخیص بده و به قول معروف Narrowing انجام بده. یک راه خوب برای حل چنین مشکلی اینه که از یک تکنیک به اسم Type Predicates استفاده کنیم:
function isString(value: any): <<value is string>> { return typeof value === 'string'; } const value = Math.random() < 0.5 ? "string" : 10; if (isString(value)) { console.log('value is a string', value.length); } else { console.log('value is not a string', value); }
عبارت value is string توی خط اول، یک Type Predicate هست. اینجا به تایپاسکریپت گفتیم که نوع پارامتر value برابر با string در نظر بگیر اگه خروجی تابع برابر با true باشه. پس هر جایی از برنامه که داریم از این تابع استفاده میکنیم و اگه انتظار داریم که خروجی اون تابع true باشه، تایپاسکریپت عملیات Narrowing انجام میده و با اون مقدار مثل یک رشته رفتار میکنه. بنابراین توی بلاک if بین خطوط ۷ تا ۹ نوع متغیر value رشته در نظر گرفته میشه.
برای اجرای کد بالا رو ببینید.
بهبود Type Predicate توی ورژن 5.5 تایپاسکریپت
خبر خوبتر اینه که توی ورژن 5.5، تایپاسکریپت تا حدودی هوشمندانه Type Predicate رو خودش اضافه میکنه و ما خودمون لازم نیست صراحتاً اون رو بنویسیم. اگه توی ورژن 5.5 چنین کدی داشته باشیم:
function isString(value: any) { return typeof value === 'string'; }
توی روی اسم تابع Hover کنین. همونطور که میبینیم تایپاسکریپت اون رو به این شکل تفسیر میکنه:
function isString(value: any): value is string
و بنابراین هنگام استفاده از اون تابع، عملیات Narrowing به درستی و بدون خطایی که قبلاً میگرفتیم انجام میگیره:
const value = Math.random() < 0.5 ? "string" : 10; if (isString(value)) { // value is string here }
خب دوستان امیدوارم از اطلاعاتی که بررسی کردیم استفاده کرده باشین. تا یه پست دیگه خدانگهدار 😉👋
