Direkt zum Hauptinhalt springen
eLearner.app
Modul 3 · Lektion 2 von 26/14 im Kurs~15 min
Lektionen des Moduls (2/2)

Generics Grundlagen

Generics (generische Programmierung) sind eine der leistungsstärksten Funktionen von TypeScript. Sie ermöglichen es, flexible und wiederverwendbare Komponenten, Funktionen und Schnittstellen zu schreiben, die mit verschiedenen Datentypen arbeiten können, während gleichzeitig die maximale Typsicherheit (Type Safety) gewahrt bleibt und die Verwendung von any vermieden wird.


Generische Funktionen

Stellen Sie sich ein Generic wie eine Variable für Typen vor. Betrachten wir eine Funktion, die den als Argument übergebenen Wert zurückgibt:

TS
function identity<T>(arg: T): T {
  return arg;
}

Der Buchstabe T (Abkürzung für Type) ist ein Platzhalter für den Typ. Wenn wir identity aufrufen, erfasst TypeScript den Typ des übergebenen Arguments und setzt T automatisch auf diesen Typ:

TS
const str = identity<string>('Hello'); // T è string
const num = identity(42); // T è number (inferito automaticamente!)

Generische Interfaces und Typ-Aliase

Generics können auch auf Interfaces und Typ-Aliase angewendet werden, um generische Container oder Datenstrukturen zu definieren:

TS
interface Box<T> {
  content: T;
}

const stringBox: Box<string> = { content: 'TypeScript' };
const numberBox: Box<number> = { content: 42 };

Mehrere Typparameter

Wir können Funktionen oder Typen definieren, die mehrere Typvariablen verwenden (z. B. T und U):

TS
function mergeObjects<T, U>(obj1: T, obj2: U): T & U {
  return { ...obj1, ...obj2 };
}

Einschränkungen für Generics (Generic Constraints)

Manchmal möchten wir die von einem Generic akzeptierten Typen einschränken. Wir können das Schlüsselwort extends verwenden, um eine Einschränkung (Constraint) hinzuzufügen.

Wenn wir beispielsweise möchten, dass der generische Typ immer eine Eigenschaft length hat (wie Strings oder Arrays):

TS
interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(arg: T): void {
  console.log(arg.length); // Sicuro! Sappiamo che arg ha 'length'
}

logLength('Hello'); // Valido
logLength([1, 2, 3]); // Valido
// logLength(42); // Errore: number non ha la proprietà length!

Probier es aus

Esercizio 1: Generische identity-Funktion

Übung#ts.m3.l2.e1
Versuche: 0Wird geladen…

Vervollständige die generische Funktion identity so, dass sie einen Parameter value vom generischen Typ T akzeptiert und diesen unverändert zurückgibt.

Editor wird geladen…
Hinweis anzeigen

Der Rückgabetyp muss derselbe generische Typ T sein wie der Parameter.

Lösung nach 3 Versuchen verfügbar

Esercizio 2: Generischer Box-Wrapper

Übung#ts.m3.l2.e2
Versuche: 0Wird geladen…

Definiere ein generisches Interface namens Box, das einen Parameter vom Typ T akzeptiert und eine einzige Eigenschaft namens content vom Typ T hat.

Editor wird geladen…
Hinweis anzeigen

Verwende die Syntax interface Box<T> { content: T; }.

Lösung nach 3 Versuchen verfügbar

Esercizio 3: Generische Einschränkung (Constraint)

Übung#ts.m3.l2.e3
Versuche: 0Wird geladen…

Schreibe eine generische Funktion namens getLength, die einen Parameter arg akzeptiert. arg muss auf ein Interface beschränkt sein, das eine Eigenschaft length (Zahl) besitzt. Die Funktion muss arg.length zurückgeben.

Editor wird geladen…
Hinweis anzeigen

Deklariere die Funktion als getLength<T extends HasLength>(arg: T): number und gib arg.length zurück.

Lösung nach 3 Versuchen verfügbar

Esercizio 4: Generisches Paar Pair

Übung#ts.m3.l2.e4
Versuche: 0Wird geladen…

Definiere ein generisches Interface Pair<T, U> mit zwei Eigenschaften: first vom Typ T und second vom Typ U. Erstelle danach eine generische Funktion makePair, die first (vom Typ T) und second (vom Typ U) akzeptiert und ein Objekt zurückgibt, das Pair<T, U> implementiert.

Editor wird geladen…
Hinweis anzeigen

Verwende die Syntax für zwei generische Parameter Pair<T, U> und deklariere makePair entsprechend.

Lösung nach 3 Versuchen verfügbar