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