Erweiterte TypeScript-Generika anhand von Beispielen erklärt

Generics in TypeScript bieten eine Möglichkeit, wiederverwendbare und flexible Codekomponenten zu erstellen, indem sie mit einer Vielzahl von Datentypen arbeiten. Erweiterte Generics gehen noch einen Schritt weiter und führen zusätzliche Funktionen wie Einschränkungen, Standardwerte und mehrere Typen ein, mit denen Entwickler robusteren und typsicheren Code schreiben können. In diesem Artikel werden diese erweiterten Konzepte in Generics anhand von Beispielen erläutert.

Allgemeine Einschränkungen

Einschränkungen begrenzen die Typen, die ein generischer Typ akzeptieren kann. Dadurch wird sichergestellt, dass der an eine generische Funktion oder Klasse übergebene Typ bestimmte Kriterien erfüllt. Beispielsweise kann eine Einschränkung verwendet werden, um sicherzustellen, dass der generische Typ eine bestimmte Eigenschaft oder Methode hat.

function getLength<T extends { length: number }>(arg: T): number {
    return arg.length;
}

const stringLength = getLength("TypeScript");
const arrayLength = getLength([1, 2, 3]);

In diesem Beispiel stellt die Einschränkung <T extends { length: number }> sicher, dass das an getLength übergebene Argument eine Eigenschaft length hat.

Mehrere Generika

TypeScript ermöglicht die Verwendung mehrerer generischer Typen in derselben Funktion, Klasse oder Schnittstelle. Dies ist nützlich, wenn mit Wertepaaren oder anderen Datenstrukturen gearbeitet wird, die mehrere Typen beinhalten.

function pair<T, U>(first: T, second: U): [T, U] {
    return [first, second];
}

const stringNumberPair = pair("TypeScript", 2024);

Diese Funktion, pair, akzeptiert zwei verschiedene generische Typen, T und U, und gibt ein Tupel zurück, das beide Typen enthält.

Standardmäßige generische Typen

Generika in TypeScript können auch Standardtypen haben. Dies ist hilfreich, wenn Sie möchten, dass ein Generikum einen Fallback-Typ hat, wenn kein spezifischer Typ angegeben ist.

function identity<T = string>(value: T): T {
    return value;
}

const defaultString = identity("Hello");  // T is string
const customNumber = identity<number>(100);  // T is number

Wenn in diesem Beispiel kein Typ an identity übergeben wird, wird standardmäßig string verwendet.

Verwenden von Generika mit Schnittstellen

Generika können mit Schnittstellen verwendet werden, um komplexe Strukturen zu definieren, bei denen die Typen nicht festgelegt sind. Dies erhöht die Flexibilität bei der Verwaltung von Daten.

interface Container<T> {
    value: T;
}

const stringContainer: Container<string> = { value: "Hello" };
const numberContainer: Container<number> = { value: 42 };

Die Schnittstelle Container ist dafür ausgelegt, Werte beliebigen Typs aufzunehmen, und ermöglicht so unterschiedliche Containerarten mit spezifischen Typen.

Generische Klassen

Klassen in TypeScript können auch generisch sein. Dies ist insbesondere beim Entwerfen von Klassen nützlich, die mit verschiedenen Datentypen arbeiten, z. B. Datenspeicher- oder Sammlungsklassen.

class DataStore<T> {
    private data: T[] = [];

    add(item: T): void {
        this.data.push(item);
    }

    getAll(): T[] {
        return this.data;
    }
}

const stringStore = new DataStore<string>();
stringStore.add("Hello");
stringStore.add("TypeScript");

const numberStore = new DataStore<number>();
numberStore.add(42);

In diesem Beispiel funktioniert die Klasse DataStore mit jedem Datentyp und bietet eine typsichere Möglichkeit zum Speichern und Abrufen von Elementen.

Abschluss

Erweiterte Generika in TypeScript sind ein leistungsstarkes Tool zum Schreiben von flexiblem, wiederverwendbarem und typsicherem Code. Durch die Verwendung von Einschränkungen, mehreren Typen, Standardwerten und Generika in Klassen und Schnittstellen können Entwickler komplexeren und robusteren Code schreiben. Das Verstehen und Anwenden dieser erweiterten Konzepte ermöglicht mehr Flexibilität und gewährleistet die Typsicherheit in allen Anwendungen.