<T>tip parametri olan generik funksiya yazmaq- Generik interfeys və tiplər təsvir etmək
- Tip parametrlərini
extendsvəkeyofilə məhdudlaşdırmaq Partial,Pick,Omit,RecordvəReturnTypeköməkçi tiplərini tətbiq etmək
Massivin ilk elementini qaytaran funksiya lazımdır: şəhərlər üçün, qiymətlər üçün, istifadəçilər üçün. Hər tip üçün ayrıca firstString, firstNumber, firstUser yazmaq mənasızdır. any isə tip məlumatını məhv edir. Aşağıdakı kod səhvsiz kompilyasiya olunur, amma işə düşəndə TypeError: city.toFixed is not a function xətası ilə çökür — kompilyator city-nin sətir olduğunu artıq bilmir:
function firstAny(items: any[]): any {
return items[0];
}
const city = firstAny(['Baku', 'Ganja']);
console.log(city.toFixed(2));Generik funksiyalar
Tipi parametr kimi qəbul edən funksiya, interfeys və ya sinif. Tip parametri bucaq mötərizəsində yazılır — adətən <T> — və çağırış zamanı konkret tiplə əvəz olunur, necə ki adi parametr konkret qiymətlə əvəz olunur.
function first<T>(items: T[]): T | undefined {
return items[0];
}
const city = first(['Baku', 'Ganja']);
const score = first([90, 75]);
const empty = first<boolean>([]);
console.log(city?.toUpperCase(), score?.toFixed(1), empty);BAKU 90.0 undefined
city-nin tipi string | undefined, score-un tipi number | undefined-dır. Massiv boş ola bildiyi üçün undefined də nəzərə alınıb.T burada «hələ məlum olmayan tip» deməkdir. first(['Baku', 'Ganja']) çağırışında TypeScript arqumentə baxır və T-nin string olduğunu özü çıxarır. Tipi açıq da göstərmək olar: first<boolean>([]). Bu, boş massiv kimi TypeScript-in tipi özü tapa bilmədiyi hallarda lazım olur.
Generik interfeyslər
Tipin özü də parametr qəbul edə bilər. Server hər dəfə eyni quruluşda cavab verir — status və verilənlər — amma verilənlər hər sorğuda fərqlidir. Hər hal üçün ayrıca interfeys yazmaq əvəzinə bir generik interfeys yazırıq. Əslində sən artıq generiklərdən istifadə etmisən: Array<string> və Promise<number> də generik tiplərdir.
interface ApiResponse<T> {
status: number;
data: T;
}
type User = { id: number; name: string };
const userResponse: ApiResponse<User> = {
status: 200,
data: { id: 1, name: 'Leyla' },
};
const tagsResponse: ApiResponse<string[]> = {
status: 200,
data: ['typescript', 'generics'],
};
console.log(userResponse.data.name, tagsResponse.data.length);Leyla 2
Məhdudiyyətlər: extends və keyof
Bəzən T «istənilən tip» ola bilməz. İki qiymətdən uzununu qaytaran funksiyaya length xassəsi lazımdır. T extends { length: number } yazılışı məhdudiyyətdir: T yalnız length xassəsi olan tip ola bilər — sətir, massiv və s. Ədədlərdə isə length yoxdur:
function longest<T extends { length: number }>(a: T, b: T): T {
return a.length >= b.length ? a : b;
}
console.log(longest('Baku', 'Sumgait'));
console.log(longest([1, 2, 3], [4, 5]));
longest(10, 20);longest.ts:7:9 - error TS2345: Argument of type 'number' is not assignable to parameter of type '{ length: number; }'.
7 longest(10, 20);
~~Sumgait və [ 1, 2, 3 ] çap edəcək.keyof T operatoru obyekt tipinin bütün açarlarının birləşməsini verir: { title: string; year: number } üçün bu, 'title' | 'year'-dir. T[K] isə həmin açardakı qiymətin tipidir. Onları birləşdirəndə yalnız mövcud xassəni qəbul edən və düzgün tipi qaytaran funksiya alınır:
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const book = { title: 'Ali and Nino', year: 1937 };
const title = getProperty(book, 'title');
const year = getProperty(book, 'year');
console.log(title.toUpperCase(), year + 1);
getProperty(book, 'author');book.ts:10:19 - error TS2345: Argument of type '"author"' is not assignable to parameter of type '"title" | "year"'.
10 getProperty(book, 'author');
~~~~~~~~title string, year isə number tipini alır. Mövcud olmayan 'author' açarı rədd edilir.Köməkçi tiplər
TypeScript-də generiklər üzərində qurulmuş hazır köməkçi tiplər var. Onlar mövcud tipdən yenisini düzəldir, beləliklə, eyni xassələri iki dəfə yazmalı olmursan. Ən çox işlənənləri bunlardır:
| Tip | Nə edir |
|---|---|
Partial<T> | bütün xassələri qeyri-məcburi edir |
Required<T> | bütün xassələri məcburi edir |
Readonly<T> | bütün xassələri yalnız oxunan edir |
Pick<T, K> | yalnız seçilmiş K xassələrini saxlayır |
Omit<T, K> | K xassələrindən başqa hamısını saxlayır |
Record<K, V> | açarları K, qiymətləri V tipli obyekt |
ReturnType<F> | F funksiyasının qaytardığı tip |
interface Product {
id: number;
name: string;
price: number;
stock: number;
}
const laptop: Product = { id: 1, name: 'Laptop', price: 1500, stock: 4 };
function update(product: Product, changes: Partial<Product>): Product {
return { ...product, ...changes };
}
type ProductCard = Pick<Product, 'name' | 'price'>;
type NewProduct = Omit<Product, 'id'>;
const card: ProductCard = { name: laptop.name, price: laptop.price };
const draft: NewProduct = { name: 'Mouse', price: 25, stock: 30 };
console.log(update(laptop, { price: 1350 }));
console.log(card, draft.name);{ id: 1, name: 'Laptop', price: 1350, stock: 4 }
{ name: 'Laptop', price: 1500 } MousePartial yeniləmə üçün (yalnız dəyişən xassələr), Omit<Product, 'id'> yeni məhsul üçün (id-ni verilənlər bazası verir), Pick isə kiçik kart üçün.type City = 'Baku' | 'Ganja' | 'Shaki';
const deliveryDays: Record<City, number> = {
Baku: 1,
Ganja: 2,
Shaki: 3,
};
function createUser(name: string, age: number) {
return { name, age, createdAt: '2025-09-01' };
}
type User = ReturnType<typeof createUser>;
const user: User = createUser('Elvin', 16);
console.log(deliveryDays.Ganja, user.name, user.createdAt);2 Elvin 2025-09-01
Record<City, number> hər şəhər üçün qiymət tələb edir: Shaki-ni unutsan, TS2741 xətası çıxacaq.Əsas fikirlər
- Generik tipi parametr kimi qəbul edir:
function first<T>(items: T[]): T | undefined. Tadətən arqumentdən çıxarılır; lazım olanda açıq yazılır:first<boolean>([]).T extends Xtip parametrini məhdudlaşdırır;K extends keyof Tyalnız mövcud açarlara icazə verir.Partial,Pick,Omit,Record,ReturnTypemövcud tiplərdən yenilərini düzəldir.- Tip parametri ən azı iki yeri əlaqələndirmirsə, generik lazım deyil.
Özünü yoxla
10 sual. Hər düzgün cavab XP qazandırır.
function first<T>(items: T[]): T | undefined yazılışında <T> nədir?