<T>tip parametreli jenerik bir fonksiyon yazmak- Jenerik arayüzler ve tipler tanımlamak
- Tip parametrelerini
extendsvekeyofile kısıtlamak Partial,Pick,Omit,RecordveReturnTypeyardımcı tiplerini uygulamak
Bir dizinin ilk elemanını döndüren bir fonksiyona ihtiyacın var: şehirler için, fiyatlar için, kullanıcılar için. Her tip için ayrı firstString, firstNumber, firstUser yazmak anlamsızdır. any ise tip bilgisini yok eder. Aşağıdaki kod hatasız derlenir ama çalışınca TypeError: city.toFixed is not a function hatasıyla çöker; derleyici artık city'nin bir string olduğunu bilmez:
function firstAny(items: any[]): any {
return items[0];
}
const city = firstAny(['Baku', 'Ganja']);
console.log(city.toFixed(2));Jenerik fonksiyonlar
Bir tipi parametre olarak alan fonksiyon, arayüz ya da sınıf. Tip parametresi açılı parantez içinde yazılır (genellikle <T>) ve her kullanımda somut bir tiple değiştirilir; tıpkı sıradan bir parametrenin somut bir değerle değiştirilmesi gibi.
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. Dizi boş olabileceği için undefined de hesaba katılmıştır.Burada T, “henüz bilinmeyen bir tip” demektir. first(['Baku', 'Ganja']) çağrısında TypeScript argümana bakar ve T'nin string olduğunu kendisi çıkarır. Tip açıkça da verilebilir: first<boolean>([]). Bu, boş bir dizide olduğu gibi TypeScript'in tipi kendisi bulamadığı durumlarda gerekir.
Jenerik arayüzler
Bir tipin kendisi de parametre alabilir. Sunucu her zaman aynı yapıda yanıt verir (bir durum kodu ve veri) ama veri her istekte farklıdır. Her durum için ayrı bir arayüz yazmak yerine tek bir jenerik arayüz yazarız. Aslında jenerikleri zaten kullandın: Array<string> ve Promise<number> da jenerik tiplerdir.
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
Kısıtlar: extends ve keyof
Bazen T “herhangi bir tip” olamaz. İki değerden uzun olanı döndüren bir fonksiyonun length özelliğine ihtiyacı vardır. T extends { length: number } yazımı bir kısıttır: T yalnızca length özelliği olan bir tip olabilir; string, dizi vb. Sayıların ise length özelliği yoktur:
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 ve [ 1, 2, 3 ] yazdırır.keyof T operatörü bir nesne tipinin tüm anahtarlarının birleşimini verir: { title: string; year: number } için bu 'title' | 'year''dır. T[K] ise o anahtardaki değerin tipidir. İkisini birleştirince yalnızca var olan özellikleri kabul eden ve tam doğru tipi döndüren bir fonksiyon elde edilir:
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 ise number tipini alır. Var olmayan 'author' anahtarı reddedilir.Yardımcı tipler
TypeScript'te jenerikler üzerine kurulmuş hazır yardımcı tipler (utility types) vardır. Var olan bir tipten yenisini üretirler; böylece aynı özellikleri iki kez yazmak zorunda kalmazsın. En sık kullanılanlar şunlardır:
| Tip | Ne yapar |
|---|---|
Partial<T> | tüm özellikleri isteğe bağlı yapar |
Required<T> | tüm özellikleri zorunlu yapar |
Readonly<T> | tüm özellikleri salt okunur yapar |
Pick<T, K> | yalnızca seçilen K özelliklerini tutar |
Omit<T, K> | K özellikleri dışında her şeyi tutar |
Record<K, V> | anahtarları K, değerleri V tipinde bir nesne |
ReturnType<F> | F fonksiyonunun döndürdüğü 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 güncelleme için (yalnızca değişen özellikler), Omit<Product, 'id'> yeni ürün için (id'yi veritabanı verir), Pick ise küçük bir kart için.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> her şehir için bir değer ister: Shaki'yi unutursan TS2741 hatası alırsın.Önemli noktalar
- Bir jenerik, tipi parametre olarak alır:
function first<T>(items: T[]): T | undefined. Tgenellikle argümandan çıkarılır; gerekirse açıkça yazılır:first<boolean>([]).T extends Xtip parametresini kısıtlar;K extends keyof Tyalnızca var olan anahtarlara izin verir.Partial,Pick,Omit,RecordveReturnTypevar olan tiplerden yenilerini üretir.- Bir tip parametresi en az iki yeri birbirine bağlamıyorsa jeneriğe gerek yoktur.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
function first<T>(items: T[]): T | undefined yazımında <T> nedir?