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:
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:
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:
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):
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):
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
Vervollständige die generische Funktion identity so, dass sie einen Parameter value vom generischen Typ T akzeptiert und diesen unverändert zurückgibt.
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
Definiere ein generisches Interface namens Box, das einen Parameter vom Typ T akzeptiert und eine einzige Eigenschaft namens content vom Typ T hat.
Hinweis anzeigen
Verwende die Syntax interface Box<T> { content: T; }.
Lösung nach 3 Versuchen verfügbar
Esercizio 3: Generische Einschränkung (Constraint)
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.
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
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.
Hinweis anzeigen
Verwende die Syntax für zwei generische Parameter Pair<T, U> und deklariere makePair entsprechend.
Lösung nach 3 Versuchen verfügbar