6-bo‘lim
Union va intersection turlari
Bir nechta turni birlashtirish, ajratuvchi maydon, never bilan to'liqlik tekshiruvi va ziddiyatli kesishma.
Ushbu bo‘lim mundarijasi
Hozirgacha har bir qiymatning bitta turi bor edi. Amalda esa
qiymat "yo shu, yo bu" bo'ladi: id - son yoki satr, to'lov -
naqd yoki karta.
Buning uchun ikkita amal bor: | (union) va & (intersection).
Union: yo u, yo bu #
let id: string | number;
id = 101;
console.log(id);
id = "A-101";
console.log(id);
tsx src/union.ts
101
A-101
Ikkalasidan tashqarisi o'tmaydi:
let id: string | number;
id = true;
tsc --noEmit 2>&1 | fold -sw 74
src/union2.ts(2,1): error TS2322: Type 'boolean' is not assignable to
type 'string | number'.
Union ustida faqat umumiy amallar #
Bu union bilan ishlashdagi birinchi to'siq:
function chop(id: string | number): void {
console.log(id.toString());
console.log(id.toUpperCase());
}
tsc --noEmit 2>&1 | fold -sw 74
src/umumiy.ts(3,18): error TS2339: Property 'toUpperCase' does not exist
on type 'string | number'.
Property 'toUpperCase' does not exist on type 'number'.
toString() ikkalasida ham bor - ruxsat. toUpperCase() faqat
satrda bor - taqiq. Xabarning ikkinchi qatori aynan qaysi
a'zoda yo'qligini aytadi.
Yechim - toraytirish:
function chop(id: string | number): string {
if (typeof id === "string") return id.toUpperCase();
return id.toFixed(0);
}
console.log(chop("a-101"));
console.log(chop(101.7));
tsx src/torayt.ts
A-101
102
if ichida id - string, tashqarisida number. TypeScript
oqimni kuzatib turadi. 7-bob to'liq shu mavzuga bag'ishlangan.
Literal union #
Union ning eng foydali ko'rinishi - aniq qiymatlar ro'yxati:
type Daraja = "boshlangich" | "orta" | "yuqori";
const d: Daraja = "orta";
console.log(d);
tsx src/literal.ts
orta
type Daraja = "boshlangich" | "orta" | "yuqori";
const d: Daraja = "qiyin";
tsc --noEmit 2>&1 | fold -sw 74
src/literal2.ts(2,7): error TS2322: Type '"qiyin"' is not assignable to
type 'Daraja'.
Ko'p hollarda enum shart emas:
| Yozuv | Ish vaqtidagi kod | Qiymati |
|---|---|---|
type D = "a" | "b" | Yo'q | "a" |
enum D { A, B } | Bor - obyekt | 0 |
Literal union kompilyatsiyadan keyin butunlay yo'qoladi va
JSON bilan to'g'ridan-to'g'ri mos tushadi. enum ni 14-bobda
solishtiramiz.
Obyekt turlarining unioni #
type Naqd = { usul: "naqd"; miqdor: number };
type Karta = { usul: "karta"; miqdor: number; raqam: string };
type Tolov = Naqd | Karta;
function chop(t: Tolov): void {
console.log(t.usul, t.miqdor);
console.log(t.raqam);
}
tsc --noEmit 2>&1 | fold -sw 74
src/tolov.ts(7,17): error TS2339: Property 'raqam' does not exist on type
'Tolov'.
Property 'raqam' does not exist on type 'Naqd'.
Bu yerda ko'pchilik adashadi: union obyektning maydonlarini qo'shmaydi, kamaytiradi. Faqat har ikkala a'zoda ham bor maydonga murojaat qilish mumkin.
Ajratuvchi maydon #
Yechim - har bir a'zoda bir xil nomli, turli literal qiymatli maydon bo'lishi:
type Naqd = { usul: "naqd"; miqdor: number };
type Karta = { usul: "karta"; miqdor: number; raqam: string };
type Tolov = Naqd | Karta;
function chop(t: Tolov): string {
if (t.usul === "karta") return `karta ${t.raqam}`;
return `naqd ${t.miqdor}`;
}
console.log(chop({ usul: "naqd", miqdor: 12000 }));
console.log(chop({ usul: "karta", miqdor: 50000, raqam: "8600" }));
tsx src/tolov2.ts
naqd 12000
karta 8600
t.usul === "karta" ni ko'rgach, TypeScript t ni Karta deb
biladi va t.raqam ochiladi. Bunday union ajratilgan union
(discriminated union) deyiladi va u TypeScript dagi eng kuchli
naqshlardan biri.
never bilan to'liqlik tekshiruvi #
Unionga yangi a'zo qo'shganda, uni ishlatadigan barcha
joylarni topish kerak. never buni kompilyatorga yuklaydi:
type Naqd = { usul: "naqd" };
type Karta = { usul: "karta" };
type Payme = { usul: "payme" };
type Tolov = Naqd | Karta | Payme;
function nomi(t: Tolov): string {
switch (t.usul) {
case "naqd":
return "Naqd pul";
case "karta":
return "Bank kartasi";
default: {
const qolgan: never = t;
return qolgan;
}
}
}
tsc --noEmit 2>&1 | fold -sw 74
src/toliq.ts(13,13): error TS2322: Type 'Payme' is not assignable to type
'never'.
Xabar aynan qaysi a'zo unutilganini aytdi: Payme.
Barcha holatlar qamralgan bo'lsa, default ga hech qachon
yetib borilmaydi va t ning turi never bo'ladi - xato
chiqmaydi. Bitta holat unutilsa - xato darhol paydo bo'ladi.
switch ning default shoxiga const qolgan: never = t;
yozib qo'ying. Endi unionga yangi a'zo qo'shsangiz,
kompilyator o'zi sizni tuzatilishi kerak bo'lgan har bir
joyga olib boradi.
Bu - "unutdim" degan xatolarni butunlay yo'q qiladigan kam sonli usullardan biri.
Massiv tuzog'i #
function qosh(royxat: string[] | number[]): void {
royxat.push("Olma");
}
tsc --noEmit 2>&1 | fold -sw 74
src/massiv.ts(2,15): error TS2345: Argument of type '"Olma"' is not
assignable to parameter of type 'never'.
never qayerdan chiqdi? royxat yo string[], yo number[].
push ikkalasida ham bor, lekin biri string, ikkinchisi
number kutadi. Ikkalasiga ham mos keladigan qiymat yo'q -
shuning uchun never.
Odatda kerakli narsa boshqasi:
const aralash: (string | number)[] = ["Olma", 12000];
aralash.push("Anor");
aralash.push(30000);
console.log(aralash.length, aralash.join(", "));
tsx src/massiv2.ts
4 Olma, 12000, Anor, 30000
| Yozuv | Ma'nosi |
|---|---|
string[] | number[] | Butun massiv yo satrli, yo sonli |
(string | number)[] | Har bir element satr yoki son |
Qavsni tushirib qoldirish - ko'p uchraydigan xato.
Intersection: ikkalasi ham #
type Shaxs = { nomi: string; yosh: number };
type Xodim = { lavozim: string; maosh: number };
type XodimShaxs = Shaxs & Xodim;
const x: XodimShaxs = {
nomi: "Husanboy",
yosh: 25,
lavozim: "dasturchi",
maosh: 9000000,
};
console.log(x.nomi, x.lavozim, x.maosh);
tsx src/kesish.ts
Husanboy dasturchi 9000000
Bittasining maydonini tushirib qoldirsak:
type Shaxs = { nomi: string; yosh: number };
type Xodim = { lavozim: string; maosh: number };
const x: Shaxs & Xodim = { nomi: "Husanboy", yosh: 25 };
tsc --noEmit 2>&1 | fold -sw 74
src/kesish2.ts(4,7): error TS2322: Type '{ nomi: string; yosh: number; }'
is not assignable to type 'Shaxs & Xodim'.
Type '{ nomi: string; yosh: number; }' is missing the following
properties from type 'Xodim': lavozim, maosh
Ziddiyatli kesishma #
Ikki turda bir xil nomli, turli turdagi maydon bo'lsa nima bo'ladi?
type A = { id: number };
type B = { id: string };
type C = A & B;
const c: C = { id: 1 };
tsc --noEmit 2>&1 | fold -sw 74
src/zid.ts(5,16): error TS2322: Type 'number' is not assignable to type
'never'.
C["id"] ning turi - never. Ya'ni "bir vaqtning o'zida ham
son, ham satr bo'lgan qiymat" mavjud emas.
E'tibor bering: type C = A & B qatori xato bermadi. Tur
bemalol yaratildi; muammo faqat unga qiymat berishga
urinilganda ko'rindi.
never ning o'zi juda g'alati tur - unga hech narsa berib
bo'lmaydi, lekin uni hamma joyga berish mumkin:
type A = { id: number };
type B = { id: string };
type C = A & B;
declare const c: C;
const son: number = c.id;
const satr: string = c.id;
c.id.toFixed(0);
tsc --noEmit 2>&1 | fold -sw 74
src/zid2.ts(10,6): error TS2339: Property 'toFixed' does not exist on
type 'never'.
c.id ni ham number ga, ham string ga berish mumkin bo'ldi
- xato yo'q. Lekin uning ustida hech qanday amal bajarib
bo'lmaydi. never - "bunday qiymat bo'lishi mumkin emas"
degani, shuning uchun u har qanday va'daga rozi.
A & B ni e'lon qilganda xato chiqmagani sizni chalg'itmasin.
Agar turlar mos kelmasa, natija never maydonli, hech qachon
to'ldirib bo'lmaydigan tur bo'ladi.
Bu ko'pincha ikkita kutubxonaning turlarini qo'shganda yuz
beradi. Shubhangiz bo'lsa, maydonni ataylab ishlatib ko'ring -
never darhol chiqadi.
Yo'nalish #
Kesishma turidagi qiymat o'z qismlariga mos keladi:
type Shaxs = { nomi: string };
type Xodim = { lavozim: string };
const ikkisi: Shaxs & Xodim = { nomi: "Husanboy", lavozim: "dasturchi" };
const faqatShaxs: Shaxs = ikkisi;
const birortasi: Shaxs | Xodim = { nomi: "Ali" };
console.log(faqatShaxs.nomi, "|", ikkisi.lavozim);
console.log("nomi" in birortasi ? birortasi.nomi : "nomsiz");
tsx src/yonalish.ts
Husanboy | dasturchi
Ali
Shaxs & Xodim ni Shaxs ga berish mumkin - unda Shaxs
talab qilgan hamma narsa bor. Teskarisi esa yo'q.
in operatori - unionni toraytirishning yana bir yo'li.
null bilan union #
function narxi(nomi: string): number | null {
return nomi === "Olma" ? 12000 : null;
}
const n = narxi("Anor");
console.log(n.toFixed(0));
tsc --noEmit 2>&1 | fold -sw 74
src/nul.ts(6,13): error TS18047: 'n' is possibly 'null'.
"Topilmadi" ni null bilan qaytarish - keng tarqalgan naqsh.
strictNullChecks uni tekshirishga majbur qiladi:
function narxi(nomi: string): number | null {
return nomi === "Olma" ? 12000 : null;
}
const a = narxi("Anor");
console.log(a === null ? "topilmadi" : a.toFixed(0));
console.log(narxi("Olma")?.toFixed(0));
console.log(narxi("Anor") ?? 0);
tsx src/nul2.ts
topilmadi
12000
0
| Operator | Nomi | Nima qiladi |
|---|---|---|
?. | Ixtiyoriy zanjir | null/undefined bo'lsa, undefined qaytaradi |
?? | Nullish birlashtirish | null/undefined bo'lsagina o'ngdagini oladi |
?? ni || bilan aralashtirmang: 0 || 5 - 5, lekin
0 ?? 5 - 0.
Xulosa #
A | B- qiymat yoA, yoB;A & B- qiymat ikkalasi ham.- Union ustida faqat barcha a'zolarda bor xossa va metodlarni ishlatish mumkin.
- Obyektlarda union maydonlarni kamaytiradi, intersection esa ko'paytiradi - nomlarga qarab teskari o'ylamang.
- Literal union (
"a" | "b") - ruxsat etilgan qiymatlar ro'yxati; u ish vaqtida hech qanday kod qoldirmaydi. - Ajratuvchi maydon (
usul: "naqd") union a'zosini aniqlab beradi va qolgan maydonlarni ochadi. defaultshoxidagiconst qolgan: never = t;unionga yangi a'zo qo'shilganda unutilgan joylarni topib beradi.string[] | number[]ga hech narsa qo'shib bo'lmaydi; kerakli yozuv odatda(string | number)[].- Ziddiyatli kesishmada maydon turi
neverbo'ladi, lekin tur e'loni xato bermaydi - muammo ishlatganda ko'rinadi. neverga hech narsa berib bo'lmaydi, lekin uni istalgan turga berish mumkin.?.va??-nullbilan union ustida ishlashning qisqa yo'llari.
string | numberturidagi o'zgaruvchi yarating va ungabooleanberib xato oling.- Union ustida faqat bitta a'zoda bor metodni chaqirib,
TS2339xabarining ikkinchi qatorini o'qing. typeofbilan toraytirib, o'sha kodni ishlaydigan qiling.- Uchta variantli literal union yarating va ro'yxatdan tashqari qiymat berib ko'ring.
usulajratuvchi maydonli ikkita to'lov turi yozing.- Ularni
ifbilan ajratib, faqat bittasida bor maydonga murojaat qiling. - Unionga uchinchi a'zo qo'shing va
nevertekshiruvi qaysi qatorni ko'rsatishini kuzating. string[] | number[]gapushqilib,neverxatosini chaqiring, keyin(string | number)[]ga o'zgartiring.- Ziddiyatli
A & Byarating va maydon turineverekanini isbotlang. number | nullqaytaruvchi funksiya yozing va natijani?.,??hamda=== null- uch xil usulda ishlating.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.