Union turlar — | operatori, narrowing bilan ishlash
Foydalanuvchining ID si qanday saqlanishi haqida bahslashasiz. Backend number ishlatadi, lekin URL dan kelganda string bo'ladi. Funksiya ikkala holatni ham qabul qilishi kerak.
JavaScript da bu muammo yo'q — istalgan narsani bersavering. TypeScript da esa aniq belgilanishi shart. Bu holat uchun — Union tur.
Union tur nima?
| (pipe) operatori bilan ikki yoki undan ko'p tur birlashtiriladi. "Bu yoki bu" degan ma'no:
type Id = number | string;
function topish(id: number | string): void {
console.log(id);
}
topish(42); // ✅ — number
topish("abc-1"); // ✅ — string
topish(true); // ❌ — boolean ruxsat yo'q
Hayotiy o'xshatma
Pochta qutisi. Ichiga xat ham keladi (qog'oz), to'lov kvitansiyasi ham (elektron). Ikki xil narsa — lekin ikkalasi ham "pochta qutisi uchun". Union tur — o'sha pochta qutisi: har xil narsalarni qabul qiladi, lekin faqat belgilanganlari.
Narrowing — qaysi tur ekanini aniqlash
Union turda ishlaganda TypeScript "bu number mi yoki string mi?" deb so'raydi. Tur aniqlanmasa — ikkala turda ham mavjud bo'lgan metodlar ishlaydi, boshqalar emas.
function uzunlik(qiymat: number | string): number {
return qiymat.length;
// ❌ — number da .length yo'q
}
Yechim — narrowing: qaysi tur ekanini tekshirib, shungacha kirisish:
function uzunlik(qiymat: number | string): number {
if (typeof qiymat === "string") {
return qiymat.length; // ✅ — bu blokda qiymat aniq string
}
return qiymat.toString().length; // ✅ — bu blokda qiymat aniq number
}
if bloki ichida TypeScript turni biladi — bu type narrowing. Faqat shu turda mavjud metodlarni ruxsat beradi.
typeof bilan narrowing
typeof — JavaScript ning o'zi:
| Tekshiruv | Natija |
|---|---|
typeof x === "string" |
string |
typeof x === "number" |
number |
typeof x === "boolean" |
boolean |
typeof x === "function" |
function |
function hisoblash(a: number | string, b: number | string) {
if (typeof a === "number" && typeof b === "number") {
return a + b; // son qo'shish
}
return `${a}${b}`; // matn birlashtirish
}
Ko'p turli union
Ikki bilan cheklanmaydi:
type Natija = "muvaffaqiyat" | "xato" | "kutilmoqda" | "bekor_qilindi";
function holatChiqar(holat: Natija): string {
if (holat === "muvaffaqiyat") return "✅ Tayyor";
if (holat === "xato") return "❌ Xato";
if (holat === "kutilmoqda") return "⏳ Kutilmoqda";
return "🚫 Bekor qilindi";
}
Bu — literal union (aniq qiymatlar to'plami). Funksiyani faqat belgilangan to'rtta qiymatdan biri bilan chaqirish mumkin.
Union va null
Union ning eng keng tarqalgan ishlatilishi — nullable tur:
type FoydalanuvchiId = number | null;
function topish(id: FoydalanuvchiId): string {
if (id === null) return "Foydalanuvchi topilmadi";
return `Foydalanuvchi ID: ${id}`;
}
null bo'lishi mumkin bo'lgan qiymatlarni T | null bilan belgilash — TypeScript ning asosiy qoidalaridan biri.
Ob'ekt union — discriminated union
Hayotiy o'xshatma
Pochta orqali ikki xil narsa kelishi mumkin: xat yoki paket. Xatda "jo'natuvchi manzili" bor, paketda "og'irlik" bor. Har birini ochishdan oldin — bu xatmi yoki paketmi ekanini bilish kerak.
Har ob'ektda "tur belgisi" (kind, type, tag) bo'lsa — TypeScript uni ishonchli ajratadi:
type Xat = { tur: "xat"; mazmun: string };
type Paket = { tur: "paket"; ogirlik: number };
type Pochta = Xat | Paket;
function qayta(pochta: Pochta): string {
if (pochta.tur === "xat") {
return pochta.mazmun; // ✅ — Xat, .mazmun mavjud
}
return `${pochta.ogirlik} kg`; // ✅ — Paket, .ogirlik mavjud
}
pochta.tur orqali TypeScript qaysi ob'ekt ekanini aniq biladi — faqat shu turda mavjud xususiyatlarga kirishga ruxsat beradi.
Tez-tez uchraydigan xatolar
Narrowingsiz union xususiyatiga kirishga urinish:
function boshliqHarfi(x: number | string): string {
return x.toUpperCase();
// ❌ — number da toUpperCase() yo'q
}
// ✅
function boshliqHarfi(x: number | string): string {
if (typeof x === "string") return x.toUpperCase();
return x.toString();
}
Discriminated union da tur xususiyatini unutish:
type Muvaffaqiyat = { natija: string };
type Xato = { xabar: string };
type Javob = Muvaffaqiyat | Xato;
function qayta(j: Javob) {
console.log(j.natija);
// ❌ — Xato da .natija yo'q, TypeScript bilmaydi qaysi tur
}
Discriminated union da har ob'ektga tur: "..." kabi belgisi bo'lishi shart.
Xulosa
| operatori — ikki yoki undan ko'p tur. "Bu yoki bu" degan ma'no.
Union bilan ishlashda narrowing kerak: typeof, === null, yoki ob'ektlarda tur belgisi orqali qaysi tur ekanini aniqlash.
Eng keng tarqalgan holat: T | null — qiymat bo'lishi ham, bo'lmasligi ham mumkin.
Discriminated union — har ob'ektda tur belgisi, TypeScript ularni ishonchli ajratadi.
Keyingi dars
13-dars: Intersection turlar — & operatori, mixin pattern