استفاده از Type Predicates در Typescript

قبل از توضیح Type Predicate، بذارید بگم که TS چجوری کار میکنه. بریم از زبون خود TS بشنویم :)« اگر type متغیرهاتون رو برای من(TS) مشخص کنین، من خودم در ادامه براتون type check انجام میدم و موقع assign کردن‌ها و ازین قبیل موارد، میتونم type هارو تشخیص بدم. اما شما اگر خودتون بخواهید وارد عمل شید و یجاهایی خودتون بصورت custom توی برنامه type ها رو تغییر بدید یا اصطلاحا type cast انجام بدید، من به شما به عنوان یه developer اعتماد میکنم و typeی که شما تعیین میکنید اولویت داره برای من »خب داستان چیه که TS انقد داره حال میده بهمون ؟ یعنی چی؟ این مثال رو ببینیداینجا اومدیم یک مقدار از جنس number رو ریختیم توی یه متغیر از جنس string که خب طبیعتا هم TS بهمون گیر میده.د ولی اگه type cast انجام بدیم و بهش بگیم که این مقدار 20 که داریم بهت assign میکنیم درواقع string هست، TS میگه اوکی و حرف ما براش سند هستش.همونطور که میبینین، با type cast ی که انجام دادیم، TS قبول کرد که مقدار ۲۰ از نوع string هستش و متدهای string رو میتونیم روش صدا بزنیم.(فقط توجه کنید که اینجا اول باید typeمون رو به unknown و بعد به string تبدیل میکردیم. چون اگه مستقیما میخواستیم type cast رو از number به string انجام بدیم، TS اجازه نمیداد و میگفت این دوتا type با هم دیگه همپوشانی ندارن یا اصطلاحا همدیگه رو overlap نمیکنن ک بخوای castشون کنی).مثالی که زدم فقط برای توضیح عملکرد TS بود و خب شما قاعدتا نباید این کارو بکنید چون توی runtime به ارور میخورید.حالا ازین قضیه میخوایم توی بحث type predicates استفاده کنیم. ممکنه با عنوان type guard هم بهش اشاره بشه. درواقع type predicate یکی از فیچرای مبحث narrowing توی TS هست که پیشنهاد میکنم در موردش یه سرچ بزنید.اول این ‌interface هایی که تعریف کردم رو درنظر بگیرید.توضیح لازم نداره ، فقط اومدم دوتا interface تعریف کردم که از Animal ارث بری میکنن و ارتیبیوت خاص خودشون رو دارن. حالا مثلا من میخوام یجایی چک کنم که آبجکتی که دارم باش کار میکنم از نوع Bird هست یا نه و اگر هست متد fly رو صدا بزنم روش. من فقط میدونم که آبجکتم از قطعا از نوع Animal هست یعنی interfaceی که برای Animal تعریف کردم رو ارضا میکنه. خب میام خیلی راحت وجود اتریبیوت fly رو چک میکنم.عه؟! ارور داد که. خب معلومه دیگه بهت اجازه نمیده که روی یک آبجکت از نوع Animal این متد رو صدا بزنی. از طرفی من اگه مطمئن بودم که آبجکت من از نوع Bird هست که دیگه اصلا چک نمیکردم. راه حل چیه؟ type predicatesمیام با استفاده از type casting یه فانکشن isBird تعریف میکنم که خروجی اون یک مقدار boolean هست.خب میبینیم که بهمون اجازه داد که متد fly رو صدا بزنیم. یعنی TS فهمید که در این صورت حتما اتریبیوت fly روی اون آبجکت وجود داره. Animal is Bird درواقع یعنی خروجی تابع ما بیان میکنه که این آبجکت از نوع Bird هست یا خیر که در واقع boolean ه. حالا این فقط یه مثال بود. خیلی جاها ما أصلا نمیدونیم type آبجکتمون چی هستش. جدا ازون این کد مشکل maintainability هم داره یعنی پس فردا اگه اتریبیوت fly عوض شد باید بیایم function رو تغییر بدیم. پس میایم یه function کلی تر و بهتر مینویسیم.خب خیلی خوب شد. fullFillsType درواقع یک type parameter میگیره به همراه parameter های obj و attr که به ما میگه که اگر این obj از نوع T باشه، آیا اتریبیوتِ attr رو داخل خودش داره یا نه. توجه کنید که attr باید از بین key های T انتخاب بشه. حالا هرجا خواستیم ببینیم که یک آبجکت یک type رو روی یک اتریبیوت خاص ارضا میکنه یا نه میتونیم از این function استفاده کنیم. بخاطر اینکه attr رو از بین key های T انتخاب کردیم، اگر این کد رو داخل ادیتورتون بزنید ، میبینید که موقع که میخاید function رو صدا بزنید و متغیر دوم رو بهش پاس بدید، TS خودش لیست مقادیر key های typeتون رو بهتون نشون میده.فیچرهای TS رو دست کم نگیرید. پیشنهاد میکنم داکیومنت TS رو خط به خط بخونید و باهاش پیش برید. فیچرها به شدت کاربردی‌ان و اطلاع نداشتن از اونا ممکنه توی روند توسعه سرعتتون رو کم بکنه و پیچیدگی کدتون زیاد بشه.اگر فیدبک، انتقاد، پیشنهاد یا هرچیز دیگه ای مدنظرتون هست خیلی ممنون میشم ازتون که برام کامنت کنین یا بهم پیام بدینLinkedIn: https://www.linkedin.com/in/sajjad-rahimi-890851231/Telegram: @sajjrhm