TypeScript'te Generikler

TypeScript'te Generikler

Bu makale, TypeScript'teki generikleri açıklar.

YouTube Video

TypeScript'te Generikler

TypeScript'teki generikler, türleri parametreleştirerek yeniden kullanılabilir ve tür güvenli işlevler, sınıflar ve arabirimler tanımlamanıza olanak tanıyan bir özelliktir. Generik kullanmak, belirli türlere bağlı olmayan kod yazmanıza olanak tanır ve böylece çeşitli türler üzerinde aynı işlemleri gerçekleştirmenizi sağlar.

Generiklerin Temelleri

Generikler, türleri argüman olarak kabul eden ve işlevlerin ve sınıfların farklı türleri işlemesine olanak tanıyan şablonlar gibi davranır.

Generik İşlevler

Aşağıdaki, argüman türleri generikler kullanılarak belirtilmiş bir işlev örneğidir.

1function identity<T>(value: T): T {
2    return value;
3}
4
5console.log(identity<number>(42));       // 42
6console.log(identity<string>("Hello"));  // Hello
  • T, işlevin argümanlarının ve dönüş değerinin türlerini temsil eden bir generik tür argümanıdır. Gerçek tür, işlev çağrıldığında belirlenir.
  • <number> veya <string> ifadesini açıkça belirterek türü belirlemiş olursunuz.

Generik türler, TypeScript'in tür çıkarımı yaptığı için açıkça belirtilmeden de çalışır.

1function identity<T>(value: T): T {
2    return value;
3}
4
5console.log(identity(42));       // 42
6console.log(identity("Hello"));  // Hello

Generikler Üzerindeki Kısıtlamalar

Generikler üzerinde kısıtlamalar koyarak, yalnızca belirli türleri kabul etmelerini sınırlayabilirsiniz.

1function loggingIdentity<T extends { length: number }>(arg: T): T {
2    console.log(arg.length);
3    return arg;
4}
5
6loggingIdentity("Hello");  // 5
7loggingIdentity([1, 2, 3]);  // 3
8
9// loggingIdentity(42);  // Error: number does not have a length property.
  • T extends { length: number } belirterek, T'nin bir length özelliğine sahip bir tür olması gerektiğini belirtirsiniz. Bu nedenle, length özelliği olmayan türler kabul edilmez.

Generik Sınıflar

Sınıflar da generikler kullanılarak tanımlanabilir. Generik sınıflar, özellikler ve yöntemler için esnek türler sunar.

 1class Box<T> {
 2    private _value: T;
 3
 4    constructor(value: T) {
 5        this._value = value;
 6    }
 7
 8    public getValue(): T {
 9        return this._value;
10    }
11
12    public setValue(value: T): void {
13        this._value = value;
14    }
15}
16
17const numberBox = new Box<number>(100);
18console.log(numberBox.getValue());  // 100
19
20const stringBox = new Box<string>("Hello");
21console.log(stringBox.getValue());  // Hello
  • Box<T>, sınıf içinde kullanılan T türünü bir generik olarak tanımlar. Bu, aynı sınıfın farklı türler için yeniden kullanılmasına olanak tanır.

Generik Arabirimler

Generikler, arabirimlerle de kullanılabilir.

 1interface Pair<T, U> {
 2    first: T;
 3    second: U;
 4}
 5
 6const numberStringPair: Pair<number, string> = { first: 1, second: "One" };
 7console.log(numberStringPair);  // { first: 1, second: 'One' }
 8
 9const booleanArrayPair: Pair<boolean, number[]> = { first: true, second: [1, 2, 3] };
10console.log(booleanArrayPair);  // { first: true, second: [ 1, 2, 3 ] }
  • Pair<T, U> ile iki generik tür belirterek, farklı türlerin bir kombinasyonu ile bir nesne tanımlayabilirsiniz.

Varsayılan Tür Argümanları

Genel tür argümanları için varsayılan bir tür belirtmek de mümkündür.

1function createArray<T = string>(length: number, value: T): T[] {
2    return Array(length).fill(value);
3}
4
5console.log(createArray(3, "a"));   // ['a', 'a', 'a']
6console.log(createArray(3, 100));   // [100, 100, 100]
  • Varsayılan tür argümanını <T = string> ile string olarak ayarlıyoruz. Herhangi bir tür açıkça belirtilmezse, T türü string olacaktır.

Genel Tür Takma İsimleri

Geneller, tür takma isimleri (type) olarak da kullanılabilir.

 1type Result<T> = {
 2    success: boolean;
 3    data: T;
 4};
 5
 6const successResult: Result<number> = { success: true, data: 42 };
 7const errorResult: Result<string> = { success: false, data: "Error occurred" };
 8
 9console.log(successResult);  // { success: true, data: 42 }
10console.log(errorResult);    // { success: false, data: 'Error occurred' }
  • Result<T> türü T olan verileri içeren bir sonuç nesnesini temsil eder. Bu şekilde, geneller kullanarak esnek tür takma isimleri oluşturabilirsiniz.

Birden Fazla Genel Tür

Birden fazla genel tür kullanarak, daha çok yönlü fonksiyonlar ve sınıflar tanımlayabilirsiniz.

1function merge<T, U>(obj1: T, obj2: U): T & U {
2    return { ...obj1, ...obj2 };
3}
4
5const person = { name: "Alice" };
6const job = { title: "Engineer" };
7
8const merged = merge(person, job);
9console.log(merged);  // { name: 'Alice', title: 'Engineer' }
  • merge fonksiyonu T ve U olarak iki farklı tür alır ve bunları birleştirerek yeni bir nesne döner.

Özet

  • Geneller türleri parametre olarak ele alarak yeniden kullanılabilir ve tür güvenli kod yazmayı sağlar.
  • Fonksiyonlar, sınıflar ve arayüzler içinde geneller kullanarak, çeşitli türleri işleyen esnek mantık yazabilirsiniz.
  • Tür argümanlarına kısıtlamalar ekleyerek veya varsayılan tür argümanlarını ayarlayarak, genellerin kapsamını kontrol edebilirsiniz.

Genelleri kullanarak tür bağımsız, genel amaçlı kod yazabilir ve TypeScript'in güçlü tür sisteminden en iyi şekilde faydalanabilirsiniz.

Yukarıdaki makaleyi, YouTube kanalımızda Visual Studio Code'u kullanarak takip edebilirsiniz. Lütfen YouTube kanalını da kontrol edin.

YouTube Video