خب توی این پست میخوایم در مورد Mapped Type ها در TS صحبت کنیم که به نظرم فیچر باحالیه و خیلی جاها میتونه کمک کنه که از تکرار کدها جلوگیری و درواقع DRY رو رعایت کنیم.
در حقیقت Mapped Type ها یک نوع Generic Type هستند که روی key های یک type دیگه iterate میکنن و برای ما یک type جدید تولید میکنن. شاید یکم گیجکننده بنظر برسه ولی اصلا اینطور نیست. بذارید با یه مثال ساده شروع کنیم.
فرض کنید ما یک type به اسم Settings داریم که شامل دو تابع برای حالت شب و نمایش پروفایل کاربر هستش.
حالا برای مثال، من میخوام یکtype دیگه درست کنم که شامل تمام پراپرتیهایSettings باشه، منتها نه به شکل تابع، بلکه به شکل اتریبیوتهای ساده از نوع boolean. برای اینکار از Mapped Type استفاده میکنیم. اول یک type مینویسم به اسم Options.
همونطور که میبینید اینجا یک type argument به اسم T داریم. با استفاده از keyof در واقعkeyهای T رو پیمایش کردیم و برای هر کدوم نوع boolean رو درنظر گرفتیم. حالا بذارید به جای T ، اونtypeی که خودمون نوشتیم یعنی Settings رو پاس بدیم و ببینیم چی میشه.
با استفاده از اینtype (یعنی Options) کاری که کردیم که type نهایی حاصل شده یعنیSettingOptions مشابه Settings هست با این تفاوت که اتریبیوت هاش از نوع boolean هستن.
به طور کلی Mapped Type ها کارشون همینه. معمولا اینطوریه که ما یکGeneric Type مینویسیم و داخل اون با استفادهkeyof، اتریبیوت های یک type رو iterate میکنیم و از آونها تایپ و اتریبیوتهای مورد نظرمون رو ایجاد میکنیم. حالا اینجا وقتی ازMapped Type ها استفاده میکنیم، موقع ایجاد type جدید از یهسری فیچرهایی برخورداریم که بنظرم خیلی باحاله و خدا میدونه چقد میتونه به کارمون بیاد. بریم چنتاشونو ببینیم.
اینجا منظور از Modifier ها فقط readonly و ? (به معنی optional) هستن. موقع استفاده ازMapped Type ها میتونیم readonly یا optional بودن اتریبیوتها رو حذف کنیم یا مثلا تمام اتریبیوت های type جدید رو optional کنیم. چجوری !؟؟ با استفاده از پیشوندهای + و –
این مثال رو ببین. اینجا با اضافه کردن readonly+ ، تعیین کردیم که type جدید همه ی اتریبیوتهاش باید readonly باشن و کسی نمیتونه تغییرشون بده. type اونهارو هم تغییر ندادیم و گذاشتیم مثل قبل بمونه. T[key] در واقع type هر کدوم از اتریبیوت های T را به ما میده. توجه کنید که key داینامیکه و داریم روی تمام اتریبیوت ها type موردنظرمون iterate می زنیم.
یا مثلا توی این قطعه کد پایین ما اومدیم و با اضافه کردن ?- ، به TS گفتیم که نمیخوایم هیچکدوم از اتریبیوتهای type جدیدمون optional باشن.
یعنی چی؟ یعنی اونجایی که داریkey های یک type روiterate میکنی، میتونی یک سری اعمال روشون انجام بدی و یا یکسری هاشون را با یکسری شرایطی حذف کنی یا مثلا اسمشون رو تغییر بدی. توی TS ورژن 4.1 به بعد با استفاده از کلمه کلیدی as میتونی اینکارو انجام بدی. اینجارو ببین چه کار باحالی انجام دادیم:)
اینجا با استفاده از ۲فیچر literal template types و key remapping اومدیم و key های Person (قبل از کلمه کلیدی as) روremap کردیم به اون چیزی که خواستیم (بعد از کلمه کلیدیas) و تبدیلشون کردیم به متد. اینم بگم که <Capitalize<string & key درواقع حرف اول key ها رو بزرگ میکنه و جزو Generic Type های تعریف شدهی خود TS هستنش. یه مثال دیگه اگه بخوام ازkey remapping بزنم اینه که ما میتونیم یکسری key هارو فیلتر کنیم.
اینجا هم روی key های Shape رو پیمایش کردیم و گفتیم میخوایم type جدیدمون همه ی اتریبیوتهای Shape رو داشته باشه به غیر ازkind و خیلی راحت تونستیم با استفاده ازExclude (که باز برای TS تعریف شدس) اینکارو انجام بدیم.
ما میتونیم در Mapped Type ها از Conditional Type ها هم استفاده کنیم و type های جدید رو با شرط های مختلف چک کنیم و درواقع conditionally تولیدشون کنیم. مثال پایین رو نگاه کنین. اینجا اومدیم برای هر اتربیوت ازObjects چک کردیم که آیا اون اتریبیوت ازShape ارث بری میکنه یا نه.
ارث بری کردن از Shape به این معنی هست که اون typeی که داره ارث بری میکنه، حتما اتریبیوت kind رو داشته باشه و مقدارشم یکی از مقادیر ‘square’ ، ‘circle’ و یا‘rectangle’ باشه.
بنظرم فیچرهای TS مبحث جذابیه و تسلط به اونها باعث میشه پروژه رو خیلی حرفهای تر دولوپ کنیم. بخاطر همین خوبه که بهشون بپردازیم و سعی میکنم بازم در مورد کاربردهاش بنویسم.
اگر فیدبک، انتقاد، پیشنهاد یا هرچیز دیگه ای مدنظرتون هست خیلی ممنون میشم ازتون که برام کامنت کنین یا بهم پیام بدین
LinkedIn: https://www.linkedin.com/in/sajjad-rahimi-890851231/
Telegram: @sajjrhm