- Birləşmə (
A | B) və kəsişmə (A & B) tiplərini yazmaq və fərqləndirmək - Tipi
typeof,in,===vənullyoxlaması ilə daraltmaq - Diskriminant birləşmə qurmaq və bütün halların işləndiyini
neverilə yoxlamaq value is Tşəklində tip mühafizəçisi yazmaq
Həyatda qiymətlər çox vaxt bir neçə formada olur. Sifarişin nömrəsi 42 də ola bilər, 'AB-17' də. Ödəniş ya kartla, ya da nağd edilir. Server ya verilənləri, ya da xəta mesajını qaytarır. Belə halları tək bir tiplə təsvir etmək olmur — «bu və ya o» lazımdır. TypeScript bunun üçün birləşmə tipləri, onlarla təhlükəsiz işləmək üçün isə daraltma təklif edir.
Birləşmə tipləri
number | string tipi «ya ədəd, ya da sətir» deməkdir. Belə qiymətlə yalnız birləşmənin bütün üzvlərində olan əməliyyatları etmək olar. Ədədin toUpperCase metodu olmadığı üçün aşağıdakı kod səhvdir:
function shout(id: number | string): string {
return id.toUpperCase();
}ids.ts:2:13 - error TS2339: Property 'toUpperCase' does not exist on type 'string | number'.
Property 'toUpperCase' does not exist on type 'number'.
2 return id.toUpperCase();
~~~~~~~~~~~Kompilyatorun sənin yoxlamalarını (typeof, in, ===, instanceof və s.) izləyərək if və ya switch budağının içində qiymətin tipini dəqiqləşdirməsi. Budağın içində birləşmədən yalnız uyğun üzv qalır.
function formatId(id: number | string): string {
if (typeof id === 'number') {
return `#${id.toString().padStart(4, '0')}`;
}
return id.toUpperCase();
}
console.log(formatId(42));
console.log(formatId('ab-17'));#0042 AB-17
if daxilində id number-dir; return-dən sonra isə yalnız string qalır.Daraltma alətləri
| Yoxlama | Nə vaxt istifadə olunur |
|---|---|
typeof x === 'string' | primitiv tiplər: string, number, boolean və s. |
x === null | null və ya undefined-ı ayırmaq |
'cardNumber' in x | fərqli xassələri olan obyektlər |
x instanceof Date | sinif nüsxələri |
x.kind === 'circle' | diskriminant birləşmələr (aşağıda) |
type Card = { cardNumber: string };
type Cash = { amount: number };
function describePayment(p: Card | Cash): string {
if ('cardNumber' in p) {
return `Card ending in ${p.cardNumber.slice(-4)}`;
}
return `Cash: ${p.amount} AZN`;
}
function greet(name: string | null): string {
if (name === null) {
return 'Hello, guest!';
}
return `Hello, ${name}!`;
}
console.log(describePayment({ cardNumber: 'XXXX-XXXX-XXXX-4821' }));
console.log(describePayment({ amount: 20 }));
console.log(greet(null), greet('Leyla'));Card ending in 4821 Cash: 20 AZN Hello, guest! Hello, Leyla!
Diskriminant birləşmələr
Ən güclü üsul birləşmənin hər üzvünə eyni adlı, amma fərqli literal qiymətli xassə verməkdir — adətən kind və ya type. Bu xassəyə diskriminant deyilir. switch (shape.kind) yazanda hər case daxilində TypeScript fiqurun dəqiq növünü bilir və yalnız onun xassələrinə icazə verir.
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'square'; side: number }
| { kind: 'rectangle'; width: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2;
case 'square':
return shape.side ** 2;
case 'rectangle':
return shape.width * shape.height;
}
}
const shapes: Shape[] = [
{ kind: 'circle', radius: 1 },
{ kind: 'square', side: 3 },
{ kind: 'rectangle', width: 2, height: 5 },
];
for (const s of shapes) {
console.log(s.kind, area(s).toFixed(2));
}circle 3.14 square 9.00 rectangle 10.00
Sabah komandadan kimsə birləşməyə üçbucaq əlavə etsə, nə olacaq? Bütün halların işləndiyinə zəmanət vermək üçün default budağında qiyməti never tipli dəyişənə yazırlar. never «heç bir qiymət» deməkdir: bütün hallar işlənibsə, oraya heç nə çatmır. İşlənməmiş hal qalıbsa, kompilyator dərhal xəbər verir:
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'square'; side: number }
| { kind: 'triangle'; base: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle':
return Math.PI * shape.radius ** 2;
case 'square':
return shape.side ** 2;
default: {
const unhandled: never = shape;
return unhandled;
}
}
}area.ts:13:13 - error TS2322: Type '{ kind: "triangle"; base: number; height: number; }' is not assignable to type 'never'.
13 const unhandled: never = shape;
~~~~~~~~~Öz tip mühafizəçilərin
Yoxlamanı ayrıca funksiyaya çıxarmaq istəsən, adi boolean qaytarmaq kifayət etmir — TypeScript funksiyanın içinə baxıb nəticə çıxarmır. Qaytarılan tipi value is string kimi yazanda funksiya tip mühafizəçisinə (type guard) çevrilir: true qaytarırsa, kompilyator qiymətin string olduğuna inanır. Bu, xüsusilə filter ilə rahatdır:
function isString(value: unknown): value is string {
return typeof value === 'string';
}
const inputs: unknown[] = ['Baku', 42, 'Ganja', null, 'Shaki'];
const cities = inputs.filter(isString);
console.log(cities.map((city) => city.toUpperCase()).join(', '));BAKU, GANJA, SHAKI
cities unknown[] yox, string[] tiplidir və toUpperCase çağırmaq olar.Kəsişmə tipləri
Birləşmə «birindən biri» deməkdirsə, kəsişmə A & B «hamısı birlikdə» deməkdir: qiymət hər iki tipin bütün xassələrinə malik olmalıdır. Kəsişmə ilə kiçik, təkrar istifadə olunan hissələrdən böyük tiplər yığmaq rahatdır:
type HasId = { id: number };
type HasDate = { createdAt: string };
type Post = HasId & HasDate & { title: string };
const post: Post = { id: 1, createdAt: '2025-09-01', title: 'Hello, TypeScript' };
console.log(`${post.id}: ${post.title} (${post.createdAt})`);1: Hello, TypeScript (2025-09-01)
Əsas fikirlər
A | B— «ya A, ya B»; birbaşa yalnız bütün üzvlərdə olan xassələri istifadə etmək olar.typeof,===,invəinstanceofyoxlamaları budağın içində tipi daraldır.- Diskriminant birləşmədə hər üzvün
kindkimi literal xassəsi olur;switchonu mükəmməl daraldır. defaultbudağındanevertipinə mənimsətmə unudulmuş halları kompilyasiya zamanı tapır.value is Tqaytaran funksiya tip mühafizəçisidir;A & Bisə hər iki tipin bütün xassələrini birləşdirir.
Özünü yoxla
10 sual. Hər düzgün cavab XP qazandırır.
if (typeof id === 'number') { ... } blokunun içində id: number | string parametri hansı tipdədir?