TypeScript Generics: So erstellen Sie wiederverwendbare Codevorlagen

TypeScript Generics werden genutzt, um wiederverwendbaren und typsicheren Code zu generieren. Das System lässt sich unter anderem auf Funktionen, Klassen, Schnittstellen und Typen anwenden.

Was sind TypeScript Generics?

In beinahe jeder Programmiersprache gibt es Tools, mit denen Nutzerinnen und Nutzer Codevorlagen erstellen können, die sich dann im späteren Verlauf oder bei weiteren Projekten wiederverwenden lassen. Ziel ist es dabei nicht nur, Zeit zu sparen, sondern auch sicheren Code zu erstellen, der sich nahtlos in neue Umgebungen einfügen lässt. Unterschiedliche Komponenten, Funktionen und komplette Datenstrukturen lassen sich auf diese Weise schreiben und replizieren, ohne dass sie dabei ihre Typsicherheit verlieren. In TypeScript werden diese Aufgaben mit Generics durchgeführt. Typen können dadurch als Parameter an andere Typen, Funktionen oder weitere Datenstrukturen weitergegeben werden.

Managed Nextcloud by IONOS Cloud
Teamarbeit in der eigenen Cloud
  • Vollständige Datensouveränität in deutschen Rechenzentren
  • Managed Service ohne Administrationsaufwand
  • File-Sharing, Dokumentenbearbeitung & Kommunikation

Syntax und Funktionsweise anhand eines einfachen Beispiels

Die Basis für die Arbeit mit TypeScript Generics sind generische Variablen. Diese funktionieren als eine Art Platzhalter und geben den Datentyp an, der zu einem späteren Zeitpunkt deklariert werden soll. Im Code kennzeichnet man sie mit einem beliebigen Großbuchstaben. Bei der Codeerstellung werden diese Variablen in spitze Klammern eingefasst. Man weist ihnen den tatsächlichen Typnamen zu, sodass anstelle des Platzhalters die gewünschte TypeScript-Funktion, Schnittstelle oder TypeScript-Klasse rückt. Diesen Platzhalter bezeichnet man auch als Type-Parameter. Es ist auch möglich, mehrere dieser Type-Parameter innerhalb einer Klammer zu platzieren. Die Syntax von TypeScript Generics erkennen Sie an diesem einfachen Beispiel:

function Beispielfunktion<T>(parameter1: T): void {
    console.log(`Der Datentyp des Parameters ${parameter1} ist: ${typeof parameter1}`)
}
typescript

Hierbei nutzen wir den Namen der Funktion („Beispielfunktion“), um die generische Variable „T“ zu definieren. Im folgenden Code deklarieren wir diese Variable als String:

Beispielfunktion<string>("Hier steht ein String.");
typescript

Übergeben wir nun den Parameterwert string an die Funktion, erhalten wir die folgende Ausgabe:

Der Datentyp des Parameters Hier steht ein String. ist: string
typescript

TypeScript Generics mit zwei Variablen

Ganz ähnlich funktionieren TypeScript Generics, wenn zwei oder mehr generische Variablen als Platzhalter eingesetzt werden. Im folgenden Beispiel hinterlegen wir die Variablen „T“ und „U“ als Typen für die Parameter „parameter1“ und „parameter2“. Sie werden dabei durch ein Komma voneinander abgetrennt:

function Beispielfunktion<T, U>(parameter1: T, parameter2: U): string {
    return JSON.stringify({parameter1, parameter2});
}
typescript

Nun weisen wir den beiden Platzhaltern Datentypen und Werte zu. In diesem Fall die Datentypen number und string sowie die Werte „11“ und „Spieler“. Dies ist der passende Code:

const str = Beispielfunktion<number, string>(11, "Spieler");
console.log(str);
typescript

Beispiele für reproduzierbare Klassen

Möchten Sie TypeScript Generics anwenden, um reproduzierbare Klassen zu erstellen, ist auch dies möglich. Im folgenden Beispiel nutzen wir Generics, um uns eine Zahl ausgeben zu lassen. Dies ist der passende Code:

class Zahlenwert<T> {
    private _value: T | undefined;
    constructor(private name: string) {}
    public setValue(value: T) {
        this._value = value;
    }
    public getValue(): T | undefined {
        return this._value;
    }
    public toString(): string {
        return `${this.name}: ${this._value}`;
    }
}
let value = new Zahlenwert<number>('meineZahl');
value.setValue(11);
console.log(value.toString());
typescript

Dadurch erhalten Sie die folgende Ausgabe:

meineZahl: 11
typescript

Das Prinzip funktioniert natürlich auch mit anderen Datentypen und mehreren generischen Variablen. Das können Sie im folgenden Beispiel sehen:

class Beispielklasse<T, U> {
vorname: T;
nachname: U;
constructor(vorname: T, nachname: U) {
	this.vorname = vorname;
	this.nachname = nachname;
	}
}
typescript

Nun weisen wir den Variablen jeweils den Datentyp String und die vorgesehenen Werte zu:

const person1 = new Beispielklasse<string, string>("Julia", "Schulz");
console.log(`${person1.vorname} ${person1.nachname}`)
typescript

Dieses Mal erhalten wir die folgende Ausgabe:

Julia Schulz
typescript

Möchten Sie unterschiedliche Datentypen kombinieren, gehen Sie wie im folgenden Beispiel vor:

class Beispielklasse<T, U> {
zahl: T;
wort: U;
constructor(zahl: T, wort: U) {
	this.zahl = zahl;
	this.wort = wort;
	}
}
typescript

Die Platzhalter bekommen nun die Datentypen number und string sowie ihre Werte zugewiesen:

const kombination = new Beispielklasse<number, string>(11, "Spieler");
console.log(`${kombination.zahl} ${kombination.wort}`);
typescript

Dies ist die Ausgabe:

11 Spieler
typescript

Einsatz mit Interfaces

Auch für Schnittstellen ist der Einsatz von TypeScript Generics möglich und sogar empfehlenswert. Das Vorgehen ähnelt der Deklarierung einer Klasse:

interface Schnittstelle<T> {
	wert: T;
}
typescript

Nun implementieren wir die Schnittstelle in die Klasse „Beispielklasse“. Dabei weisen wir der Variablen „T“ den Datentyp string zu:

class Beispielklasse implements Schnittstelle<string> {
	wert: string = "Dies ist ein Beispiel mit einem Interface";
}
const ausgabe = new Beispielklasse();
console.log(ausgabe.wert)
typescript

Unsere Ausgabe sieht dadurch aus wie folgt:

Dies ist ein Beispiel mit einem Interface
typescript

Generische Arrays erstellen

Für TypeScript Arrays ist der Einsatz der TypeScript Generics ebenfalls möglich. Hier ein einfaches Codebeispiel, bei dem wir die Funktion reverse nutzen, um die Zahlenreihung eines Arrays umzudrehen:

function reverse<T>(array: T[]): T[] {
    return array.reverse();
}
let zahlen: number[] = [10, 7, 6, 13, 9];
let neueReihung: number[] = reverse(zahlen);
console.log(neueReihung);
typescript

Wir erhalten dadurch diese Ausgabe:

[9, 13, 6, 7, 10]
typescript

TypeScript Generics für bedingte Typen

Abschließend zeigen wir Ihnen noch, wie Sie mit TypeScript Generics Typen mit einer Bedingung nutzen. Das Resultat ändert sich dabei, je nachdem, ob eine Bedingung erfüllt wird oder nicht. Im folgenden Beispiel soll diese Voraussetzung der Datentyp string sein. Dies ist der Code:

type IstDiesEinString<T> = T extends string ? true : false;
type A = "beispiel";
type B = {
	name: string;
};
type ErstesResultat = IstDiesEinString<A>;
type ZweitesResultat = IstDiesEinString<B>;
typescript

type A ist also der String „beispiel“, während type B ein Objekt mit der Eigenschaft „name“ und dem Datentyp string ist. Diese beiden Typen hinterlegen wir dann als „ErstesResultat“ und „ZweitesResultat“. Überprüfen wir anschließend die beiden Types, werden wir feststellen, dass „ErstesResultat“ als String den Wert true erhält, während „ZweitesResultat“ false bleibt.

Tipp

Deployment direkt via GitHub: Deploy Now von IONOS ist dank automatischer Framework-Erkennung, einem schnellen Setup und optimaler Skalierbarkeit die beste Wahl für Websites und Apps gleichermaßen. Wählen Sie den passenden Tarif für Ihr Projekt!

Page top