O'zbek

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;
};

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

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.

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

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.