TypeScript'ning Mapped Type va Conditional Type'lari bo'yicha to'liq qo'llanma. Amaliy misollar va ilg'or qo'llash holatlari bilan tanishing.
TypeScript'ning Mapped Type va Conditional Type'larini O'zlashtirish
JavaScript'ning ustki to'plami bo'lgan TypeScript mustahkam va qo'llab-quvvatlanishi oson ilovalar yaratish uchun kuchli imkoniyatlarni taqdim etadi. Bu imkoniyatlar orasida Mapped Types va Conditional Types ilg'or tip manipulyatsiyasi uchun muhim vositalar sifatida ajralib turadi. Ushbu qo'llanma ushbu tushunchalarning sintaksisi, amaliy qo'llanilishi va ilg'or foydalanish holatlarini o'rganib, ularning to'liq sharhini taqdim etadi. Tajribali TypeScript dasturchisi bo'lasizmi yoki endigina o'z safaringizni boshlayapsizmi, ushbu maqola sizni bu imkoniyatlardan samarali foydalanish uchun zarur bilimlar bilan qurollantiradi.
Mapped Types nima?
Mapped Types mavjud tiplarni o'zgartirish orqali yangi tiplar yaratishga imkon beradi. Ular mavjud tipning xususiyatlari bo'yicha iteratsiya qilib, har bir xususiyatga transformatsiya qo'llaydi. Bu, ayniqsa, barcha xususiyatlarni ixtiyoriy (optional) yoki faqat o'qish uchun (read-only) qilish kabi mavjud tiplarning variantlarini yaratish uchun foydalidir.
Asosiy Sintaksis
Mapped Type sintaksisi quyidagicha:
type NewType<T> = {
[K in keyof T]: Transformation;
};
T
: Siz map qilmoqchi bo'lgan kiruvchi tip.K in keyof T
: KiruvchiT
tipidagi har bir kalit bo'yicha iteratsiya qiladi.keyof T
T
dagi barcha xususiyat nomlarining birlashmasini (union) yaratadi vaK
iteratsiya davomida har bir alohida kalitni ifodalaydi.Transformation
: Har bir xususiyatga qo'llamoqchi bo'lgan transformatsiyangiz. Bu modifikator (masalan,readonly
yoki?
) qo'shish, tipni o'zgartirish yoki butunlay boshqa narsa bo'lishi mumkin.
Amaliy Misollar
Xususiyatlarni Faqat O'qish Uchun Qilish
Aytaylik, sizda foydalanuvchi profilini ifodalovchi interfeys bor:
interface UserProfile {
name: string;
age: number;
email: string;
}
Siz barcha xususiyatlari faqat o'qish uchun bo'lgan yangi tip yaratishingiz mumkin:
type ReadOnlyUserProfile = {
readonly [K in keyof UserProfile]: UserProfile[K];
};
Endi, ReadOnlyUserProfile
UserProfile
bilan bir xil xususiyatlarga ega bo'ladi, lekin ularning barchasi faqat o'qish uchun bo'ladi.
Xususiyatlarni Ixtiyoriy Qilish
Xuddi shunday, siz barcha xususiyatlarni ixtiyoriy qilishingiz mumkin:
type OptionalUserProfile = {
[K in keyof UserProfile]?: UserProfile[K];
};
OptionalUserProfile
UserProfile
ning barcha xususiyatlariga ega bo'ladi, lekin har bir xususiyat ixtiyoriy bo'ladi.
Xususiyat Tiplarini O'zgartirish
Siz har bir xususiyatning tipini ham o'zgartirishingiz mumkin. Misol uchun, barcha xususiyatlarni satr (string) turiga o'zgartirishingiz mumkin:
type StringifiedUserProfile = {
[K in keyof UserProfile]: string;
};
Bunday holda, StringifiedUserProfile
dagi barcha xususiyatlar string
tipida bo'ladi.
Conditional Types nima?
Conditional Types sizga shartga bog'liq bo'lgan tiplarni aniqlash imkonini beradi. Ular biror tip ma'lum bir cheklovga mos kelishiga qarab tip munosabatlarini ifodalash usulini taqdim etadi. Bu JavaScript'dagi ternar operatoriga o'xshaydi, lekin tiplar uchun.
Asosiy Sintaksis
Conditional Type sintaksisi quyidagicha:
T extends U ? X : Y
T
: Tekshirilayotgan tip.U
:T
tomonidan kengaytirilayotgan tip (shart).X
: AgarT
U
ni kengaytirsa (shart rost bo'lsa), qaytariladigan tip.Y
: AgarT
U
ni kengaytirmasa (shart yolg'on bo'lsa), qaytariladigan tip.
Amaliy Misollar
Tipning Satr Ekanligini Aniqlash
Keling, agar kiruvchi tip satr bo'lsa, string
, aks holda number
qaytaradigan tip yaratamiz:
type StringOrNumber<T> = T extends string ? string : number;
type Result1 = StringOrNumber<string>; // string
type Result2 = StringOrNumber<number>; // number
type Result3 = StringOrNumber<boolean>; // number
Birlashmadan (Union) Tipni Chiqarib Olish
Siz birlashma (union) tipidan ma'lum bir tipni chiqarib olish uchun shartli tiplardan foydalanishingiz mumkin. Masalan, `null` bo'lmagan tiplarni chiqarib olish uchun:
type NonNullable<T> = T extends null | undefined ? never : T;
type Result4 = NonNullable<string | null | undefined>; // string
Bu yerda, agar T
null
yoki undefined
bo'lsa, tip never
ga aylanadi, keyin esa TypeScript'ning birlashma tipini soddalashtirishi orqali filtrlanadi.
Tiplarni Chiqarish (Infer)
Shartli tiplar, shuningdek, infer
kalit so'zi yordamida tiplarni chiqarish uchun ham ishlatilishi mumkin. Bu sizga murakkabroq tip tuzilmasidan tipni chiqarib olish imkonini beradi.
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
function myFunction(x: number): string {
return x.toString();
}
type Result5 = ReturnType<typeof myFunction>; // string
Ushbu misolda, ReturnType
funksiyaning qaytariladigan tipini chiqarib oladi. U T
ning istalgan argumentlarni qabul qiladigan va R
tipini qaytaradigan funksiya ekanligini tekshiradi. Agar shunday bo'lsa, u R
ni qaytaradi; aks holda, u any
ni qaytaradi.
Mapped Types va Conditional Types'ni Birlashtirish
Mapped Types va Conditional Types'ning haqiqiy kuchi ularni birlashtirishdan kelib chiqadi. Bu sizga juda moslashuvchan va ifodali tip transformatsiyalarini yaratish imkonini beradi.
Misol: Chuqur Readonly (Deep Readonly)
Keng tarqalgan qo'llash holatlaridan biri bu obyektning barcha xususiyatlarini, jumladan, ichki (nested) xususiyatlarni ham faqat o'qish uchun qiladigan tip yaratishdir. Bunga rekursiv shartli tip yordamida erishish mumkin.
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
interface Company {
name: string;
address: {
street: string;
city: string;
};
}
type ReadonlyCompany = DeepReadonly<Company>;
Bu yerda, DeepReadonly
barcha xususiyatlarga va ularning ichki xususiyatlariga readonly
modifikatorini rekursiv ravishda qo'llaydi. Agar xususiyat obyekt bo'lsa, u o'sha obyektda DeepReadonly
ni rekursiv ravishda chaqiradi. Aks holda, u shunchaki xususiyatga readonly
modifikatorini qo'llaydi.
Misol: Xususiyatlarni Tip Bo'yicha Filtrlash
Aytaylik, siz faqat ma'lum bir tipdagi xususiyatlarni o'z ichiga olgan tip yaratmoqchisiz. Bunga erishish uchun Mapped Types va Conditional Types'ni birlashtirishingiz mumkin.
type FilterByType<T, U> = {
[K in keyof T as T[K] extends U ? K : never]: T[K];
};
interface Person {
name: string;
age: number;
isEmployed: boolean;
}
type StringProperties = FilterByType<Person, string>; // { name: string; }
type NonStringProperties = Omit<Person, keyof StringProperties>;
Ushbu misolda, FilterByType
T
ning xususiyatlari bo'yicha iteratsiya qiladi va har bir xususiyatning tipi U
ni kengaytirishini tekshiradi. Agar kengaytirsa, u xususiyatni natijaviy tipga qo'shadi; aks holda, kalitni never
ga map qilib, uni chiqarib tashlaydi. Kalitlarni qayta map qilish uchun "as" dan foydalanilganiga e'tibor bering. Keyin biz asl interfeysdan satrli xususiyatlarni olib tashlash uchun `Omit` va `keyof StringProperties` dan foydalanamiz.
Ilg'or Qo'llash Holatlari va Patternlar
Asosiy misollardan tashqari, Mapped Types va Conditional Types yuqori darajada moslashtiriladigan va tip-xavfsiz ilovalar yaratish uchun yanada ilg'or stsenariylarda qo'llanilishi mumkin.
Taqsimlanuvchi (Distributive) Conditional Types
Tekshirilayotgan tip birlashma (union) tipi bo'lganda, shartli tiplar taqsimlanuvchi bo'ladi. Bu shartning birlashmaning har bir a'zosiga alohida qo'llanilishini va natijalar keyin yangi birlashma tipiga birlashtirilishini anglatadi.
type ToArray<T> = T extends any ? T[] : never;
type Result6 = ToArray<string | number>; // string[] | number[]
Ushbu misolda, ToArray
string | number
birlashmasining har bir a'zosiga alohida qo'llaniladi va natijada string[] | number[]
hosil bo'ladi. Agar shart taqsimlanuvchi bo'lmaganida, natija (string | number)[]
bo'lar edi.
Utility Types'dan Foydalanish
TypeScript Mapped Types va Conditional Types'dan foydalanadigan bir nechta o'rnatilgan utility tiplarni taqdim etadi. Ushbu utility tiplar murakkabroq tip transformatsiyalari uchun qurilish bloklari sifatida ishlatilishi mumkin.
Partial<T>
:T
ning barcha xususiyatlarini ixtiyoriy qiladi.Required<T>
:T
ning barcha xususiyatlarini majburiy qiladi.Readonly<T>
:T
ning barcha xususiyatlarini faqat o'qish uchun qiladi.Pick<T, K>
:T
danK
xususiyatlar to'plamini tanlaydi.Omit<T, K>
:T
danK
xususiyatlar to'plamini olib tashlaydi.Record<K, T>
:K
xususiyatlar to'plami vaT
tipiga ega bo'lgan tip yaratadi.Exclude<T, U>
:T
danU
ga tayinlanishi mumkin bo'lgan barcha tiplarni chiqarib tashlaydi.Extract<T, U>
:T
danU
ga tayinlanishi mumkin bo'lgan barcha tiplarni chiqarib oladi.NonNullable<T>
:T
dannull
vaundefined
ni chiqarib tashlaydi.Parameters<T>
:T
funksiya tipining parametrlarini oladi.ReturnType<T>
:T
funksiya tipining qaytariladigan tipini oladi.InstanceType<T>
:T
konstruktor funksiya tipining instansiya tipini oladi.
Ushbu utility tiplar murakkab tip manipulyatsiyalarini soddalashtirishi mumkin bo'lgan kuchli vositalardir. Misol uchun, siz faqat ma'lum xususiyatlarni ixtiyoriy qiladigan tip yaratish uchun Pick
va Partial
ni birlashtirishingiz mumkin:
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
interface Product {
id: number;
name: string;
price: number;
description: string;
}
type OptionalDescriptionProduct = Optional<Product, "description">;
Ushbu misolda, OptionalDescriptionProduct
Product
ning barcha xususiyatlariga ega, ammo description
xususiyati ixtiyoriydir.
Template Literal Types'dan Foydalanish
Template Literal Types sizga satr literallariga asoslangan tiplar yaratish imkonini beradi. Ular dinamik va ifodali tip transformatsiyalarini yaratish uchun Mapped Types va Conditional Types bilan birgalikda ishlatilishi mumkin. Masalan, siz barcha xususiyat nomlarini ma'lum bir satr bilan boshlanadigan tip yaratishingiz mumkin:
type Prefix<T, P extends string> = {
[K in keyof T as `${P}${string & K}`]: T[K];
};
interface Settings {
apiUrl: string;
timeout: number;
}
type PrefixedSettings = Prefix<Settings, "data_">;
Ushbu misolda, PrefixedSettings
data_apiUrl
va data_timeout
xususiyatlariga ega bo'ladi.
Eng Yaxshi Amaliyotlar va Mulohazalar
- Sodda Saqlang: Mapped Types va Conditional Types kuchli bo'lishiga qaramay, ular kodingizni murakkablashtirishi ham mumkin. Tip transformatsiyalaringizni iloji boricha sodda saqlashga harakat qiling.
- Utility Types'dan Foydalaning: Iloji boricha TypeScript'ning o'rnatilgan utility tiplaridan foydalaning. Ular yaxshi sinovdan o'tgan va kodingizni soddalashtirishi mumkin.
- Tiplaringizni Hujjatlashtiring: Tip transformatsiyalaringizni, ayniqsa ular murakkab bo'lsa, aniq hujjatlashtiring. Bu boshqa dasturchilarga kodingizni tushunishga yordam beradi.
- Tiplaringizni Sinovdan O'tkazing: Tip transformatsiyalaringiz kutilganidek ishlayotganiga ishonch hosil qilish uchun TypeScript'ning tip tekshiruvidan foydalaning. Tiplaringizning ishlashini tekshirish uchun unit testlar yozishingiz mumkin.
- Ishlash Samaradorligini Hisobga Oling: Murakkab tip transformatsiyalari TypeScript kompilyatoringizning ishlash samaradorligiga ta'sir qilishi mumkin. Tiplaringizning murakkabligiga e'tiborli bo'ling va keraksiz hisob-kitoblardan saqlaning.
Xulosa
Mapped Types va Conditional Types TypeScript'dagi kuchli xususiyatlar bo'lib, ular sizga yuqori darajada moslashuvchan va ifodali tip transformatsiyalarini yaratish imkonini beradi. Ushbu tushunchalarni o'zlashtirib, siz TypeScript ilovalaringizning tip xavfsizligini, qo'llab-quvvatlanishini va umumiy sifatini yaxshilashingiz mumkin. Xususiyatlarni ixtiyoriy yoki faqat o'qish uchun qilish kabi oddiy transformatsiyalardan tortib, murakkab rekursiv transformatsiyalar va shartli mantiqgacha, bu xususiyatlar sizga mustahkam va kengaytiriladigan ilovalar yaratish uchun kerakli vositalarni taqdim etadi. Ularning to'liq salohiyatini ochish va yanada malakali TypeScript dasturchisi bo'lish uchun ushbu xususiyatlarni o'rganishda va tajriba qilishda davom eting.
TypeScript safaringizni davom ettirar ekansiz, rasmiy TypeScript hujjatlari, onlayn hamjamiyatlar va ochiq manbali loyihalar kabi mavjud bo'lgan boy resurslardan foydalanishni unutmang. Mapped Types va Conditional Types kuchini qabul qiling, shunda siz hatto eng qiyin tip bilan bog'liq muammolarni ham hal qilishga yaxshi tayyor bo'lasiz.