Ali Torki
خواندن ۶ دقیقه·۲ ماه پیش

تحلیل جبرگونه و ریاضیاتی any، unknown و never در TypeScript

تفاوت Any, Unknown و Never از دیدگاه نظریهٔ جبر مجموعه‌ها و ریاضیات
تفاوت Any, Unknown و Never از دیدگاه نظریهٔ جبر مجموعه‌ها و ریاضیات


تفاوت Any، Unknown و Never از دیدگاهِ نظریّهٔ جبرِ مجموعه‌ها و ریاضیّات

سعی می‌کنم توی این نوشته، از دیدگاهِ نظریّهٔ جبرِ مجموعهٔ‌ها و تئوری تایپ، تفاوت این سه تایپ any، unknown و never رو به صورت مختصر و مفید توضیح بدم.

البته قبلش لازمهٔ چهارتا مفهوم پایه‌ای از تئوری مجموعهٔ‌ها رو بدونیم تا درک و دید بهتری برای مقایسهٔ و تحلیلِ نحوهٔ عملکردشون داشتهٔ باشیم:

1. اگه "T" یه تایپ باشهٔ، اون‌وقت "{T}" مجموعهٔ‌ای از همهٔ عناصریهٔ که از نوع "T" هستن.

2. عملگر Union در تایپ‌اسکریپت "(|)" در واقع، متناظر با عملگرِ اجتماع "(∪)" در جبرِ مجموعهٔ‌هاست.

3. عملگر Intersection در تایپ‌اسکریپت "(&)" همون اشتراکٔ "(∩)" در تئوریِ مجموعهٔ‌هاست.

4. رابطهٔ SubType "(<:)" رو می‌شهٔ با زیرمجموعهٔ‌بودن "(⊆)" مطابقت داد.

با این پیش‌زمینهٔ، حالا هر سهٔ تایپِ never، unknown و any هرکدوم جایگاهِ ویژهٔ خودشون رو توی این ساختار دارن که در ادامهٔ، هر کدوم رو توضیح می‌دم. البته قبلش لازمهٔ تفسیر و معنی کلمهٔ "کاردینالیتهٔ" رو کوتاه توضیح بدم که در ادامهٔ صحبت‌هام، چند باری نقل قول کردم ازش.

کاردینالیتهٔ (Cardinality) توی جبر مجموعهٔ‌ها یا همون تئوری مجموعهٔ‌ها، در واقع اشاره داره به «تعداد اعضای» یه مجموعهٔ یا به بیان ساده‌تر «اندازهٔ» اون مجموعهٔ رو تعریف می‌کنهٔ. حالا این اندازه ممکنهٔ متناهی باشه (مثلاً یه مجموعهٔ با ۵ تا عضو) یا نامتناهی (مثل اعداد طبیعی که بی‌نهایت عضو دارن). پس اگه بگم کاردینالیتهٔ یه مجموعهٔ چقدره، یعنی دقیقاً دارم می‌گم چند تا عنصر می‌تونهٔ توی اون مجموعهٔ باشه و یا حضور پیدا کنهٔ.


حالا نوبت می‌رسهٔ به تفسیر و موشکافی هر کدوم از این سهٔ تایپ و تحلیل عملکردشون زیر ذره‌بین.


تایپ never

از دیدِ ریاضی می‌شهٔ گفت این تایپ همون «مجموعهٔ تهی» (∅) هستش؛ یعنی اصلاً مقداری توش نمی‌گنجهٔ. توی تئوریِ تایپ‌ها بهش می‌گن «Bottom Type». به این معنی کهٔ تابعی کهٔ مقدارش never برمی‌گردهٔ، یا Throw Error کرده یا اینکهٔ توی یه حلقهٔ بی‌نهایت گیر افتادهٔ. و همین‌طور از اون‌جایی که ∅ زیرمجموعهٔ هر مجموعهٔ دیگه‌ای به حساب میاد، پس در سطح تایپ هم never یک SubType از همهٔ تایپ‌هاست. احتمالا بپرسید این یعنی چی؟

بذارید اینطوری بگم کهٔ از دیدگاهٔ جبر مجموعه‌ٔها، مجموعهٔ تهی (∅) یعنی اینکهٔ هیچ عنصری توش وجود ندارهٔ یا به عبارت دیگه T⊈∅. حالا چرا می‌گیم ∅ زیرمجموعۀ همه مجموعه‌ٔهای دیگهٔ به حساب میاد؟ چون یکی از تعریف‌های زیرمجموعه‌ٔبودن اینه که «همهٔ عناصر مجموعهٔ اول، توی مجموعهٔ دوم هم باشن». خب وقتی هیچ عنصری نداری، اصولاً چیزی هم نیست که بیرون از مجموعهٔ دوم قرار بگیره. پس به‌عبارت دیگهٔ، می‌تونیم اینطوری تعبیر کنیم که شرط زیرمجموعه‌ٔبودن همیشه صادقهٔ، چون هیچ موردی وجود ندارهٔ که نقض‌اش کنهٔ.

از این طرف، توی دنیای تایپ‌ها و تایپ‌اسکریپت، وقتی حرف از never می‌زنیم یعنی معادل ∅ به حساب میاد، و این یعنی در حقیقت هیچ مقداری نمی‌شه‌‌ٔ بهش اختصاص داد یا به عبارت دیگه Assign کرد، چون هیچ تایپ‌ای وجود ندارهٔ که بشهٔ از نوع never باشهٔ. پس طبیعیه‌ٔ که اگر یه تابعی قرارهٔ مقدارش never برگرده‌ٔ، معنیش این میشهٔ که یا این تابع اصلاً خروجی‌ای برنمی‌گردونه (دچار یک حلقهٔ بی‌نهایت یا Infinite Loop شدهٔ) یا یک Throw Error‌ کرده و کلاً نقطۀ پایانی هم ندارهٔ.

حالا چون توی ریاضیات زیرمجموعۀ هر مجموعهٔ دیگه‌ای محسوب می‌شهٔ، توی دنیای تایپ‌ها هم never یک SubType از همهٔ تایپ‌ها به حساب میاد. یعنی اگه جایی از کدت انتظار داری یه نوع خاص باشهٔ مقدارش، این واقعیت که never هیچ مقداری نداره، جادویی رو می‌کنهٔ که بتونی اون رو (از لحاظ تئوری) به هر نوع (تایپ داده) دیگه‌ٔای تغییر بدی یا در حقیقت Type Casting کنی، بدون اینکه با تناقض وجودیتش مواجه بشی. توی تایپ‌اسکریپت اگر یه متغیر یا یه تابع بتونه never باشهٔ، عملأ می‌شه با قطعیت گفت که هیچ‌وقت قرار نیست مقدار واقعی از اون تایپ داده رو داشتهٔ باشی، پس هر ترکیبی که نیاز باشهٔ، می‌تونه در سطح تئوری سازگار بمونه در مورد این تایپ.


تایپ unknown

این یکی رو می‌تونیم «مجموعهٔ Universal Set یا جهانی» با نمادِ اختصاری (U) در جبر بدونیم و همینطور در تئوری تایپ، یه «Top Type» به حساب میاد. حال از نگاهِ کاردینالیتهٔ، تایپ unknown می‌تونهٔ دربرگیرندهٔ همه‌چیز (مقدار و یا نوع داده) باشه(TUsafe​). اما نکتهٔ مهم اینه که برای دسترسی به متدها یا propertyهای مختلف‌اش، باید حتماً نوع داده‌اش رو Narrow یا چک کنیم که به یک مفهوم از یک تئوری دیگه‌ای به اسم Type Guard در تایپ‌اسکریپت هم نشأت می‌گیره.به همین خاطرهٔ که unknown در نهایت امر، یک تایپ شدیدأ محافظه‌کار و مطمئن به‌حساب میاد؛ یعنی توی کدت مجبوری همیشه در مواجهه با این تایپ مراقب باشی و قبل از استفاده ازش، حتمأ نوع‌ داده‌ای که با خودش حمل می‌کنه رو بررسی کنی (narrowing) تا امکان دسترسی بهش رو پیدا کنی. به تعبیر دیگه‌ای، این تایپ نوع‌های مختلفی از نقاب‌ها رو همیشه بر چهره‌اش داره که در هر مکان و زمانی‌ می‌تونهٔ خودش رو در جلوه دیتا تایپ‌ای که شما انتظار دارید نمایان کنهٔ و به سازگاری موقتی برسهٔ!

حالا اگر بخوایم این unknown رو زیر زره‌بین و با جزئیات بیشتری تحلیل کنیم می‌تونیم همچین تعریفی داشته باشیم کهٔ وقتی می‌گیم unknown می‌تونهٔ دربرگیرندهٔ همه‌چیز باشهٔ، یعنی مثل یه «مجموعهٔ جهانی» (Universal Set) عمل می‌کنهٔ. در بحث مجموعه‌ٔها، مجموعهٔ جهانی (U) یه جورایی بزرگ‌ترین مجموعهٔ توی یه فضای مفهومی مشخص محسوب می‌شهٔ که شامل تمام اعضای ممکن اون فضاست.

حالا با این تعاریف، توی تایپ‌اسکریپت هم unknown به همین شکل می‌تونهٔ پذیرای هر نوع مقداری باشه (از عدد و رشتهٔ گرفتهٔ تا آبجکت‌ها و فانکشن‌ها و غیرهٔ). پس در واقع از دید کاردینالیتهٔ، می‌تونیم بگیم که unknown بیشترین ظرفیت رو برای قرار گرفتن هر نوع عنصری رو در خودش داره. که صد البتهٔ unknown محبوب‌ترین تایپ من‌ بوده تا به امروز.


تایپ any

بازم از نگاهِ نظریهٔ مجموعه‌ها می‌شه گفت که مثل تایپ unknown این تایپ‌هم یک مجموعه U یا همون مجموعهٔ جهانیه (Universal Set) به حساب می‌آد؛ ولی این یکی اصلاً محافظه‌کار نیست و هیچ‌وقت نمی‌تونه بهت اون حس اطمینان و خاطرِ جمعی که بخاطرش کد می‌زنی رو بده. چرا؟ چون کامپایلر رو دور می‌زنه و حالا هر عملیات/تغییری رو می‌تونی روش انجام بدی بدون این‌که خطأ تایپ بگیری و به همین سادگی ما بهترین قابلیت تایپ‌اسکریپت یعنی (Type Safety) رو از دست می‌دیم. برای همین هم می‌گن که any راهِ فرار یا خروج اضطراری از سیستم دست و پا گیر تایپ‌ها به‌حساب میاد و بهت کمک می‌کنهٔ تا قوانین کامپایلر رو اونطوری دور بزنی که دیگه اصول و اخلاقی نباشه که بخوای بهشون پابند بمونی.


اگه بخوام خلاصهٔ و چکیدهٔ تمام صحبت‌هام رو بگم تا مروری بکنیم:

• تایپ never دقیقاً تهی (∅) یا Bottom Type هستش و هیچ مقداری رو در بر نمی‌گیره.

• تایپ unknown عملاً مجموعهٔ جهانی (U) ولی مطمئن و محافظه‌کاره و باید برای استفاده، حتماً Narrowing کنیم.

• تایپ any هم از نگاهِ نظریهٔ کاردینالیته مثل Uـه، ولی Type Safety رو نادیده می‌گیره و سیستم Type Checking کامپایلر رو به تعبیری غیرفعال می‌کنه.


در پایان، امیدوارم این نوشته دیدِ مختصر و مفیدی در موردِ درک بهتر نظریّهٔ جبرِ این سه تایپ و نوعِ عملکرد و تفاوتشون بهتون داده باشه تا توی نوشتنِ کدهاتون با تایپ‌اسکریپت، زین پس از این سه تایپِ خاص و دوست داشتنی، به‌درستی و به‌جا استفاده کنین.


من همیشهٔ می‌توانم آزادانهٔ انتخاب کنم، اما باید بدانم که اگر انتخاب نکنم، باز هم انتخابی کرده‌ام.

ژان پل سارتر


موفق باشید

Technical Team Lead
شاید از این پست‌ها خوشتان بیاید