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

۱۶ بازدید
آخرین به‌روزرسانی: ۲۶ اسفند ۱۳۹۸
زمان مطالعه: ۲ دقیقه
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-های با کلید/اعضای قوی در تایپ اسکریپت دست یافتیم. به این منظور صرفاً باید مطمئن شوید که از نام‌گذاری نوع بهتری در کدهای واقعی پروداکشن خود استفاده می‌کنید.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۱ نفر
آیا این مطلب برای شما مفید بود؟
شما قبلا رای داده‌اید!
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
better-programming

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *