Map با کلید قوی در تایپ اسکریپت — از صفر تا صد

منظور از Map با کلید قوی این است که Map را چنان بیان کنیم که تنها شامل کلیدهایی باشد که در دامنه اعضای همان نوع T یافت میشود. به بیان سادهتر تنها کلیدهایی معتبر هستند که با مشخصه دارای نام یکسان در هر نوع مفروض T متناظر باشند. این مفهوم را میتوان به صورت زیر بیان کرد:
type StronglyKeyedMap<T, K extends keyof T, V> = { [k in K]: V }
اینک با استفاده از یک نوع واقعی اقدام به وهلهسازی میکنیم:
interface Foo { x : number; y : string; z : boolean; } type FooTrueSKM = StronglyKeyedMap<Foo, keyof Foo, true>
کد فوق موجب میشود تنها اعضای Foo مجاز باشند و هر یک باید به مقدار متناظر true نگاشت شوند:
const example : FooTrueSKM = { x : true, y : true, a : true, // not ok because `a` does not exist in `Foo` z : 123, // not ok because not mapped to true }
این کد کار میکند، اما استفاده هرباره از keyof یعنی انواع اندیس در وهلهسازی کمی دشوار است و از این رو یک سطح دیگر از تجرید برای حل این مشکل ارائه میکنیم:
type SKM<T, V> = StronglyKeyedMap<T, keyof T, V> type FooTrueSKM = SKM<Foo, true> // one less type argument
مشکل دوم استفاده از FooTrueSKM است که موجب عدم موفقیت در این بررسی میشود که آیا همه اعضای Foo در map وجود دارند یا نه. اما در غالب موارد میخواهیم تنها یک زیرمجموعه از کلیدها داشته باشیم. خوشبختانه تایپ اسکریپت یک نوع کاربردی <Partial<T ارائه کرده است که میتوان مورد استفاده قرار داد:
type FooTrueSKM = Partial<SKM<Foo, true>> // now partial
یعنی میتوان به صورت زیر عمل کرد:
const example : FooTrueSKM = { x : true, y : true // note: omitting `z` would fail typechecking without Partial<T> }
بدین ترتیب یک راهحل کاملاً تعمیمیافته حاصل میشود که میتوان برای بیان اطلاعات مرتبط در مورد یک وهله خاص بدون نیاز به آلوده ساختن تعریف نوع زیرین مورد استفاده قرار دارد.
Enum-ها
راهحلی که در بخش قبلی معرفی کردیم در مواردی که نوع واقعه T در عمل یک enum باشد نیز کار میکند، اما به کمی کار بیشتر نیاز دارد. تعریف enum زیر را در نظر بگیرید:
enum Bar { hello, world }
اگر بخواهیم از همین راهبرد بنیادی برای وهلهسازی نوع استفاده کنیم:
type BarSKM = Partial<StronglyKeyedMap<Bar, keyof Bar, true>>; const example : BarSKM = { hello : true }
موجب شکست بررسی نوع میشود زیرا map در برابر مشخصههای غیرصریح enum یعنی toString, valueOf و غیره کلیدبندی شده است. با این حال ما میخواهیم یک map با حافظه قوی داشته باشیم، یعنی تنها کلیدهای ما در map یک enum را به حافظه بسپارند. شاید فکر کنید میتوان از typeof به همراه keyof استفاده کرد:
type BarSMM = Partial<StronglyKeyedMap<typeof Bar, keyof Bar, true>>
اکنون گرچه به راهحل نزدیک شدهایم، اما همچنان مشکل به قوت خود باقی است. تعریف صحیح به صورت زیر است:
type BarSMM = Partial<StronglyKeyedMap<typeof Bar, keyof typeof Bar, true>>
به typeof اضافی در آرگومان دامنه کلیدها توجه داشته باشید:
const example : BarSMM = { hello : true, // ok! toString : true // not ok because `toString` is not in key domain }
سخن پایانی
در این مقاله به یک راهحل برای تعریف map-های با کلید/اعضای قوی در تایپ اسکریپت دست یافتیم. به این منظور صرفاً باید مطمئن شوید که از نامگذاری نوع بهتری در کدهای واقعی پروداکشن خود استفاده میکنید.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- مجموعه آموزشهای برنامهنویسی
- راهنمای جامع تایپ اسکریپت (Typescript) — از صفر تا صد
- قابلیتهای جدید و جالب تایپ اسکریپت ۳.۶ — راهنمای کاربردی
- انواع پیشرفته در تایپ اسکریپت – از صفر تا صد
==