در تایپ اسکریپت، Exclude utility type این امکان را به ما میدهد تا اعضای خاصی از یک تایپ union تعریف شده را حذف کنیم. این بدان معناست که ما میتوانیم یک تایپ موجود را انتخاب کنیم و مواردی را برای موقعیتهای خاص از آن حذف نماییم. در این مقاله قصد داریم تا Exclude در تایپ اسکریپت و نحوه استفاده از آن را باهم بررسی کنیم.
type Fruit = 'apple' | 'banana' | 'orange' type Result = Exclude<Fruit, 'orange'> // 'apple' | 'banana'
میتوانیم برای حذف یک عضو از union از Exclude استفاده کنیم. آرگومان اول union کامل را نشان میدهد و آرگومان دوم نماینده عضوی است که باید حذف شود.
از نظر فنی، آرگومان دوم میتواند هر تایپی داشته باشد. اگر بخواهیم عضوی را که وجود ندارد حذف کنیم، دراین صورت تایپ اسکریپت هیچ خطایی برنمیگرداند بلکه فقط union اصلی را return میکند.
type Result = Exclude<Fruit, 'pear'> // 'apple' | 'banana' | 'orange'
type Event = 'click' | 'focus' | 'change' | 'abort' type ClickAndFocusEvent = Exclude<Event, 'change' | 'abort'> // 'click' | 'focus'
همچنین میتوانیم برای حذف چند عضو از یک union نیز از Exclude استفاده کنیم. با انتقال یک union به آرگومان دوم، میتوانیم چندین عضو را همزمان حذف نماییم.
همانند مورد قبلی، اینجا هم لازم نیست همه آن اعضا در union اصلی وجود داشته باشند:
type ClickAndFocusEvent = Exclude<Event, 'change' | 'abort' | 'blur'> // 'click' | 'focus'
type Event =
| {
type: 'click'
}
| {
type: 'focus'
}
| {
type: 'change'
}
discriminated union یک unionای است که معمولاً از آبجکتها تشکیل شده است. این آبجتها دارای ویژگیهای مشترکی هستند که میتوانیم از آن برای تمایز بین آبجکتها استفاده کنیم. در مثال بالا، از ویژگی typeبرای تمایز بین رویدادهای مختلف استفاده میشود.
ما میتوانیم زیرمجموعهای از union را با استفاده از Exclude برای حذف همه اعضایی که مقدار خاصی برای ویژگی typeندارند، extract کنیم.
type ClickAndFocusEvent = Exclude<Event, {type: 'change'}> // { type: 'click' } | { type: 'focus' }
این موضوع حتی در صورتی که اعضای union دارای ویژگیهای دیگری باشند نیز صادق میباشد.
type Event =
| {
type: 'click'
x: number
y: number
}
| {
type: 'focus'
}
| {
type: 'change'
value: string
}
type ClickAndFocusEvent = Exclude<Event, {type: 'click'}> // { type: 'focus' } | { type: 'change', value: string }
در مثال بالا، ویژگیهای xو yنیازی به ارسال به Exclude برای حذف رویداد clickندارند.
type Event =
| {
type: 'click'
}
| {
type: 'focus'
}
| {
type: 'change'
}
| {
type: 'abort'
}
type ClickAndFocusEvent = Exclude<Event, {type: 'change'} | {type: 'abort'}> // { type: 'click' } | { type: 'focus' }
همچنین میتوانیم با انتقال یک union به آرگومان دوم، چندین عضو از یک discriminated union را حذف کنیم. این میتواند unionای از اعضای آن union باشد یا unionای از ویژگی type:
type ClickAndFocusEvent = Exclude<Event, {type: 'change' | 'abort'}> // { type: 'click' } | { type: 'focus' }
type Routes =
| {
route: '/user'
search: {
id: string
}
}
| {
route: '/user/create'
}
| {
route: '/user/edit'
search: {
id: string
}
}
type RoutesWithoutSearch = Exclude<
Routes,
{
search: any
}
> // { route: '/user/create' }
باید به این نکته توجه کنیم که نیازی به اضافه کردن «discriminator» (در این مثال، route) در آرگومان دوم برای Exclude نداریم. ما فقط میتوانیم شکل اعضایی که میخواهیم حذف کنیم را ارسال نماییم.
در مثال بالا، میخواهیم همه اعضای union Routesکه دارای ویژگی searchهستند را حذف کنیم.
type PossibleTypes = 'admin' | 'user' | 0 | 1 | 2 type StringTypes = Exclude<PossibleTypes, number> // ^? 'admin' | 'user'
Exclude همچنین روی تایپهای پایهای نیز کار میکند. در مثال بالا، قصد داریم تا تمام حروفی که با numberمطابقت دارند را از union PossibleTypesحذف نماییم.
اگر بخواهیم تمام stringها، numberها و یا booleanها را ازیک union حذف کنیم این کار میتواند مفید باشد.
type ObjectKey = 'userId' | 'postId' | 'userName' | 'postName'
type PostKey = Exclude<ObjectKey, `${string}${'user'}${string}`> // 'postName' | 'postId'
میتوانیم از Exclude برای حذف تمام رشتهها از union که حاوی یک زیررشته خاص هستند استفاده کنیم.
در مثال بالا، ما تمام رشتههایی که حاوی زیررشته userمیباشند را از union ObjectKeyحذف میکنیم.
ما از یک قالب literal برای نشان دادن رشتهای که میخواهیم حذف نماییم استفاده میکنیم، در این مثال رشته userاست. سپس از دستور ${string}برای نشان دادن هر رشتهای که قبل یا بعد از رشته فرعی که میخواهیم حذف کنیم استفاده میکنیم.
type ObjectKey = 'userId' | 'postId' | 'id' | 'userName' | 'postName'
type NonIdKey = Exclude<ObjectKey, `${string}${'id' | 'Id'}${string}`> // 'postName' | 'userName'
همچنین میتوانیم از Exclude برای حذف تمام رشتهها از unionای که یکی از چندین رشته فرعی ممکن را دربرمیگیرد استفاده کنیم.
در مثال بالا، ما تمام رشتههایی را که حاوی idیا IDهستند را از union ObjectKeyحذف میکنیم. با انتقال یک union به الگوی literal، میتوانیم چندین زیررشته را در یک زمان حذف نماییم.
type ObjectKey = 'userId' | 'postId' | 'id' | 'userName' | 'postName'
type NonNameKey = Exclude<ObjectKey, `${string}Name`> // 'userId' | 'postId' | 'id'
میتوانیم از Exclude برای حذف تمام رشتهها از یک union که پیشوند یا پسوند خاصی دارند استفاده کنیم.
در مثال بالا، ما تمام رشتههایی که به Nameختم میشوند را از union ObjectKeyحذف مینماییم.
در اینجا،دستور ${string}برای نشان دادن یک رشته با هر طولی که قبل از رشته فرعی که میخواهیم حذف کنیم، استفاده میشود. برای این که پیشوند مورد نظر ما پیشوند خاصی مطابقت داشته باشد، میتوانیم ${string} را به عنوان literal به انتهای الگو منتقل کنیم.
Exclude یک utility type بسیار قدرتمند در تایپ اسکریپت است که میتواند برای کاربردهای مختلف مورد استفاده قرار بگیرد.