Murakkab shartli va xaritalangan tiplar bilan TypeScript kuchini oching. Murakkab ma'lumotlar tuzilmalariga moslashadigan moslashuvchan, tip-xavfsiz ilovalar yaratishni o'rganing. Haqiqatan ham dinamik TypeScript kodini yozish san'atini egallang.
Murakkab TypeScript Paternlari: Shartli va Xaritalangan Tiplarni Mahorat bilan Egallash
TypeScript'ning kuchi uning kuchli tiplashtirishni ta'minlash qobiliyatida yotadi, bu sizga xatolarni ertaroq aniqlash va yanada barqaror kod yozish imkonini beradi. string
, number
va boolean
kabi asosiy tiplar fundamental bo'lsa-da, TypeScript'ning shartli va xaritalangan tiplar kabi ilg'or xususiyatlari moslashuvchanlik va tip xavfsizligining yangi o'lchamini ochib beradi. Ushbu keng qamrovli qo'llanma ushbu kuchli tushunchalarni chuqur o'rganib, sizni haqiqatan ham dinamik va moslashuvchan TypeScript ilovalarini yaratish uchun bilimlar bilan qurollantiradi.
Shartli Tiplar Nima?
Shartli tiplar, JavaScript'dagi ternar operatorga o'xshash (condition ? trueValue : falseValue
), shartga bog'liq tiplarni aniqlash imkonini beradi. Ular biror tipning ma'lum bir cheklovga mos kelishi yoki kelmasligiga asoslanib, murakkab tip munosabatlarini ifodalashga yordam beradi.
Sintaksis
Shartli tipning asosiy sintaksisi:
T extends U ? X : Y
T
: Tekshirilayotgan tip.U
: Qarshi tekshiriladigan tip.extends
: Quyi tip munosabatini bildiruvchi kalit so'z.X
: AgarT
niU
ga tayinlash mumkin bo'lsa, ishlatiladigan tip.Y
: AgarT
niU
ga tayinlash mumkin bo'lmasa, ishlatiladigan tip.
Mohiyatan, agar T extends U
rost (true) deb baholansa, tip X
ga aylanadi; aks holda, u Y
ga aylanadi.
Amaliy Misollar
1. Funksiya Parametrining Tipini Aniqlash
Aytaylik, siz funksiya parametrining satr (string) yoki raqam (number) ekanligini aniqlaydigan tip yaratmoqchisiz:
type ParamType<T> = T extends string ? string : number;
function processValue(value: ParamType<string | number>): void {
if (typeof value === "string") {
console.log("Qiymat satr:", value);
} else {
console.log("Qiymat raqam:", value);
}
}
processValue("hello"); // Natija: Qiymat satr: hello
processValue(123); // Natija: Qiymat raqam: 123
Ushbu misolda ParamType<T>
shartli tipdir. Agar T
satr bo'lsa, tip string
ga aylanadi; aks holda, u number
ga aylanadi. processValue
funksiyasi ushbu shartli tipga asoslanib, satr yoki raqamni qabul qiladi.
2. Kirish Tipiga Asosan Qaytariladigan Tipni Chiqarish
Kirish ma'lumotlariga qarab turli tiplarni qaytaradigan funksiyangiz borligini tasavvur qiling. Shartli tiplar sizga to'g'ri qaytariladigan tipni aniqlashga yordam beradi:
interface StringProcessor {
process(input: string): number;
}
interface NumberProcessor {
process(input: number): string;
}
type Processor<T> = T extends string ? StringProcessor : NumberProcessor;
function createProcessor<T extends string | number>(input: T): Processor<T> {
if (typeof input === "string") {
return { process: (input: string) => input.length } as Processor<T>;
} else {
return { process: (input: number) => input.toString() } as Processor<T>;
}
}
const stringProcessor = createProcessor("example");
const numberProcessor = createProcessor(42);
console.log(stringProcessor.process("example")); // Natija: 7
console.log(numberProcessor.process(42)); // Natija: "42"
Bu yerda, Processor<T>
tipi kirish ma'lumotining tipiga qarab StringProcessor
yoki NumberProcessor
ni shartli ravishda tanlaydi. Bu createProcessor
funksiyasining to'g'ri turdagi protsessor obyektini qaytarishini ta'minlaydi.
3. Ajratilgan Unionlar (Discriminated Unions)
Shartli tiplar ajratilgan unionlar bilan ishlashda juda kuchli. Ajratilgan union — bu har bir a'zosi umumiy, yagona tipdagi xususiyatga (diskriminant) ega bo'lgan union tipidir. Bu sizga o'sha xususiyatning qiymatiga qarab tipni toraytirish imkonini beradi.
interface Square {
kind: "square";
size: number;
}
interface Circle {
kind: "circle";
radius: number;
}
type Shape = Square | Circle;
type Area<T extends Shape> = T extends { kind: "square" } ? number : string;
function calculateArea(shape: Shape): Area<typeof shape> {
if (shape.kind === "square") {
return shape.size * shape.size;
} else {
return Math.PI * shape.radius * shape.radius;
}
}
const mySquare: Square = { kind: "square", size: 5 };
const myCircle: Circle = { kind: "circle", radius: 3 };
console.log(calculateArea(mySquare)); // Natija: 25
console.log(calculateArea(myCircle)); // Natija: 28.274333882308138
Ushbu misolda, Shape
tipi ajratilgan uniondir. Area<T>
tipi shaklning kvadrat yoki aylana ekanligini aniqlash uchun shartli tipdan foydalanadi va kvadratlar uchun number
, aylanalar uchun esa string
qaytaradi (garchi real hayotda siz bir xil qaytariladigan tiplarni xohlashingiz mumkin bo'lsa-da, bu printsipni namoyish etadi).
Shartli Tiplar Haqida Asosiy Xulosalar
- Shartlarga asoslangan tiplarni aniqlash imkonini beradi.
- Murakkab tip munosabatlarini ifodalash orqali tip xavfsizligini yaxshilaydi.
- Funksiya parametrlari, qaytariladigan tiplar va ajratilgan unionlar bilan ishlash uchun foydalidir.
Xaritalangan Tiplar Nima?
Xaritalangan tiplar mavjud tiplarning xususiyatlarini xaritalash orqali ularni o'zgartirish usulini taqdim etadi. Ular sizga boshqa tipning xususiyatlariga asoslanib, xususiyatlarni ixtiyoriy, faqat o'qish uchun qilish yoki ularning tiplarini o'zgartirish kabi o'zgartirishlarni qo'llagan holda yangi tiplar yaratish imkonini beradi.
Sintaksis
Xaritalangan tipning umumiy sintaksisi:
type NewType<T> = {
[K in keyof T]: ModifiedType;
};
T
: Kirish tipi.keyof T
:T
dagi barcha xususiyat kalitlarining unionini qaytaruvchi tip operatori.K in keyof T
:keyof T
dagi har bir kalit bo'ylab iteratsiya qiladi va har bir kalitniK
tip o'zgaruvchisiga tayinlaydi.ModifiedType
: Har bir xususiyat xaritalanadigan tip. Bu shartli tiplar yoki boshqa tip o'zgartirishlarini o'z ichiga olishi mumkin.
Amaliy Misollar
1. Xususiyatlarni Ixtiyoriy Qilish
Mavjud tipning barcha xususiyatlarini ixtiyoriy qilish uchun xaritalangan tipdan foydalanishingiz mumkin:
interface User {
id: number;
name: string;
email: string;
}
type PartialUser = {
[K in keyof User]?: User[K];
};
const partialUser: PartialUser = {
name: "John Doe",
}; // To'g'ri, chunki 'id' va 'email' ixtiyoriy
Bu yerda, PartialUser
User
interfeysining kalitlari bo'ylab iteratsiya qiluvchi xaritalangan tipdir. Har bir K
kaliti uchun u ?
modifikatorini qo'shish orqali xususiyatni ixtiyoriy qiladi. User[K]
User
interfeysidan K
xususiyatining tipini oladi.
2. Xususiyatlarni Faqat O'qish Uchun Qilish
Xuddi shunday, mavjud tipning barcha xususiyatlarini faqat o'qish uchun qilishingiz mumkin:
interface Product {
id: number;
name: string;
price: number;
}
type ReadonlyProduct = {
readonly [K in keyof Product]: Product[K];
};
const readonlyProduct: ReadonlyProduct = {
id: 123,
name: "Example Product",
price: 25.00,
};
// readonlyProduct.price = 30.00; // Xato: 'price' ga qiymat berib bo'lmaydi, chunki u faqat o'qish uchun mo'ljallangan xususiyat.
Bu holda, ReadonlyProduct
Product
interfeysining har bir xususiyatiga readonly
modifikatorini qo'shadigan xaritalangan tipdir.
3. Xususiyat Tiplarini O'zgartirish
Xaritalangan tiplar, shuningdek, xususiyatlarning tiplarini o'zgartirish uchun ham ishlatilishi mumkin. Masalan, siz barcha satr xususiyatlarini raqamlarga aylantiradigan tip yaratishingiz mumkin:
interface Config {
apiUrl: string;
timeout: string;
maxRetries: number;
}
type NumericConfig = {
[K in keyof Config]: Config[K] extends string ? number : Config[K];
};
const numericConfig: NumericConfig = {
apiUrl: 123, // Xaritalash tufayli raqam bo'lishi kerak
timeout: 456, // Xaritalash tufayli raqam bo'lishi kerak
maxRetries: 3,
};
Ushbu misol xaritalangan tip ichida shartli tipdan foydalanishni namoyish etadi. Har bir K
xususiyati uchun u Config[K]
tipining satr ekanligini tekshiradi. Agar shunday bo'lsa, tip number
ga xaritalanadi; aks holda, u o'zgarishsiz qoladi.
4. Kalitlarni Qayta Xaritalash (TypeScript 4.1 dan boshlab)
TypeScript 4.1 as
kalit so'zi yordamida xaritalangan tiplar ichida kalitlarni qayta xaritalash imkoniyatini taqdim etdi. Bu sizga asl tipga asoslanib, turli xususiyat nomlari bilan yangi tiplar yaratish imkonini beradi.
interface Event {
eventId: string;
eventName: string;
eventDate: Date;
}
type TransformedEvent = {
[K in keyof Event as `new${Capitalize<string&K>}`]: Event[K];
};
// Natija:
// {
// newEventId: string;
// newEventName: string;
// newEventDate: Date;
// }
//Capitalize funksiyasi birinchi harfni katta harfga o'zgartirish uchun ishlatiladi
type Capitalize<S extends string> = Uppercase<string&S> extends never ? string : `$Capitalize<S>`;
//Haqiqiy obyekt bilan ishlatish
const myEvent: TransformedEvent = {
newEventId: "123",
newEventName: "New Name",
newEventDate: new Date()
};
Bu yerda, TransformedEvent
tipi har bir K
kalitini "new" prefiksi bilan va bosh harfi kattalashtirilgan yangi kalitga qayta xaritalaydi. `Capitalize` yordamchi funksiyasi kalitning birinchi harfini katta harfga o'zgartirishni ta'minlaydi. `string & K` kesishmasi biz faqat satr kalitlari bilan ishlayotganimizni va K dan to'g'ri literal tipni olayotganimizni ta'minlaydi.
Kalitlarni qayta xaritalash tiplarni muayyan ehtiyojlarga moslashtirish va o'zgartirish uchun kuchli imkoniyatlar ochadi. Bu sizga murakkab mantiq asosida kalitlarni qayta nomlash, filtrlash yoki o'zgartirish imkonini beradi.
Xaritalangan Tiplar Haqida Asosiy Xulosalar
- Mavjud tiplarni ularning xususiyatlari bo'yicha xaritalash orqali o'zgartirish imkonini beradi.
- Xususiyatlarni ixtiyoriy, faqat o'qish uchun qilish yoki ularning tiplarini o'zgartirishga imkon beradi.
- Boshqa tipning xususiyatlariga asoslanib yangi tiplar yaratish uchun foydalidir.
- Kalitlarni qayta xaritalash (TypeScript 4.1 da kiritilgan) tip o'zgartirishlarida yanada katta moslashuvchanlikni taqdim etadi.
Shartli va Xaritalangan Tiplarni Birlashtirish
Shartli va xaritalangan tiplarning haqiqiy kuchi ularni birlashtirganda namoyon bo'ladi. Bu sizga keng doiradagi stsenariylarga moslasha oladigan juda moslashuvchan va ifodali tip ta'riflarini yaratish imkonini beradi.
Misol: Xususiyatlarni Tip bo'yicha Filtrlash
Aytaylik, siz obyektning xususiyatlarini ularning tipiga qarab filtrlaydigan tip yaratmoqchisiz. Masalan, siz obyektdan faqat satr (string) xususiyatlarini ajratib olmoqchi bo'lishingiz mumkin.
interface Data {
name: string;
age: number;
city: string;
country: string;
isEmployed: boolean;
}
type StringProperties<T> = {
[K in keyof T as T[K] extends string ? K : never]: T[K];
};
type StringData = StringProperties<Data>;
// Natija:
// {
// name: string;
// city: string;
// country: string;
// }
const stringData: StringData = {
name: "John",
city: "New York",
country: "USA",
};
Ushbu misolda, StringProperties<T>
tipi kalitlarni qayta xaritalash va shartli tipga ega bo'lgan xaritalangan tipdan foydalanadi. Har bir K
xususiyati uchun u T[K]
tipining satr ekanligini tekshiradi. Agar shunday bo'lsa, kalit saqlanib qoladi; aks holda, u never
ga xaritalanadi va uni samarali ravishda filtrlaydi. Xaritalangan tip kaliti sifatida never
natijaviy tipdan uni olib tashlaydi. Bu StringData
tipiga faqat satr xususiyatlari kiritilishini ta'minlaydi.
TypeScript'dagi Yordamchi Tiplar (Utility Types)
TypeScript umumiy tip o'zgartirishlarini bajarish uchun shartli va xaritalangan tiplardan foydalanadigan bir nechta o'rnatilgan yordamchi tiplarni taqdim etadi. Ushbu yordamchi tiplarni tushunish kodingizni sezilarli darajada soddalashtirishi va tip xavfsizligini yaxshilashi mumkin.
Keng Tarqalgan Yordamchi Tiplar
Partial<T>
:T
ning barcha xususiyatlarini ixtiyoriy qiladi.Readonly<T>
:T
ning barcha xususiyatlarini faqat o'qish uchun qiladi.Required<T>
:T
ning barcha xususiyatlarini majburiy qiladi. (?
modifikatorini olib tashlaydi)Pick<T, K extends keyof T>
:T
danK
xususiyatlar to'plamini tanlaydi.Omit<T, K extends keyof T>
:T
danK
xususiyatlar to'plamini olib tashlaydi.Record<K extends keyof any, T>
:K
xususiyatlar to'plamiga ega bo'lgan va har birining tipiT
bo'lgan tipni 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 ajratib oladi.NonNullable<T>
:T
dannull
vaundefined
ni chiqarib tashlaydi.Parameters<T>
:T
funksiya tipining parametrlarini tuple (kortaj) shaklida oladi.ReturnType<T>
:T
funksiya tipining qaytariladigan tipini oladi.InstanceType<T>
:T
konstruktor funksiya tipining namuna (instance) tipini oladi.ThisType<T>
: Kontekstualthis
tipi uchun marker bo'lib xizmat qiladi.
Ushbu yordamchi tiplar shartli va xaritalangan tiplar yordamida qurilgan bo'lib, bu TypeScript'ning ilg'or xususiyatlarining kuchini va moslashuvchanligini namoyish etadi. Masalan, Partial<T>
quyidagicha aniqlanadi:
type Partial<T> = {
[P in keyof T]?: T[P];
};
Shartli va Xaritalangan Tiplardan Foydalanishning Eng Yaxshi Amaliyotlari
Shartli va xaritalangan tiplar kuchli bo'lsa-da, agar ehtiyotkorlik bilan ishlatilmasa, ular kodingizni murakkablashtirishi mumkin. Quyida yodda tutish kerak bo'lgan ba'zi eng yaxshi amaliyotlar keltirilgan:
- Sodda tuting: Haddan tashqari murakkab shartli va xaritalangan tiplardan saqlaning. Agar tip ta'rifi juda chalkash bo'lib qolsa, uni kichikroq, boshqarilishi osonroq qismlarga bo'lishni o'ylab ko'ring.
- Ma'noli nomlardan foydalaning: Shartli va xaritalangan tiplaringizga ularning maqsadini aniq ko'rsatuvchi tavsiflovchi nomlar bering.
- Tiplaringizni hujjatlashtiring: Shartli va xaritalangan tiplaringiz ortidagi mantiqni tushuntirish uchun izohlar qo'shing, ayniqsa ular murakkab bo'lsa.
- Yordamchi tiplardan foydalaning: Maxsus shartli yoki xaritalangan tip yaratishdan oldin, o'rnatilgan yordamchi tip xuddi shu natijaga erisha oladimi-yo'qligini tekshiring.
- Tiplaringizni sinovdan o'tkazing: Turli stsenariylarni qamrab oluvchi birlik testlarini yozish orqali shartli va xaritalangan tiplaringiz kutilganidek ishlashiga ishonch hosil qiling.
- Ishlash samaradorligini hisobga oling: Murakkab tip hisob-kitoblari kompilyatsiya vaqtiga ta'sir qilishi mumkin. Tip ta'riflaringizning ishlash samaradorligiga e'tibor bering.
Xulosa
Shartli va xaritalangan tiplar TypeScript'ni mahorat bilan egallash uchun muhim vositalardir. Ular sizga murakkab ma'lumotlar tuzilmalari va dinamik talablarga moslashadigan yuqori darajada moslashuvchan, tip-xavfsiz va barqaror ilovalar yaratish imkonini beradi. Ushbu qo'llanmada muhokama qilingan tushunchalarni tushunib, qo'llash orqali siz TypeScript'ning to'liq salohiyatini ochishingiz va yanada mustahkam va kengaytiriladigan kod yozishingiz mumkin. TypeScript'ni o'rganishda davom etar ekansiz, qiyin tiplashtirish muammolarini hal qilishning yangi usullarini topish uchun shartli va xaritalangan tiplarning turli kombinatsiyalarini sinab ko'rishni unutmang. Imkoniyatlar haqiqatan ham cheksizdir.