Generics (generische Typen) ermöglichen es, universellen Code zu schreiben, der mit verschiedenen Typen arbeitet und gleichzeitig strenge Typensicherheit gewährleistet.
Syntax:
function identity<T>(value: T): T { return value; } const x = identity<string>('test'); // T = string
Anwendungsgebiete:
Beispiel mit Typbeschränkung:
function getFirst<T extends { length: number }>(arr: T): T { return arr[0]; }
Frage: Ist es notwendig, einen konkreten Typ beim Aufruf einer Funktion mit einem Generics-Parameter anzugeben?
Antwort:
Nicht unbedingt. TypeScript leitet (inferred) die Typen anhand der übergebenen Werte ab, wenn möglich. Manchmal ist es jedoch praktisch, den Typ explizit anzugeben, zum Beispiel wenn aus den Werten der Typ nicht klar ist oder mehrere Varianten vorhanden sind.
function identity<T>(value: T): T { return value; } identity(5); // T = number (auto) identity<string>('s'); // T = string (explizit)
Geschichte
In einem E-Commerce-Projekt wurde ein generisches Repository für verschiedene Entitäten erstellt, aber die Typbeschränkung wurde vergessen. Dadurch konnte in das Generische beliebiges Objekt gespeichert werden, und es wurde einmal eine Entität mit inkompatiblen Feldern gespeichert. Die Typen schützten nicht vor Fehlern.
Geschichte
Eine generische Funktion erhielt ein Array, erwartete ein Array mit Typ der Elemente. Aber die Funktion gab any[] zurück, da die Generics nicht explizit angegeben wurden und TypeScript den Typ nicht ableiten konnte. Der Fehler wurde erst im Produktionsbetrieb bemerkt.
Geschichte
Ein unerfahrener Entwickler erstellte eine generische Klasse ohne Typbeschränkung, nutzte ein Feld, das nicht in allen Typen vorhanden war. Der Compiler gab keine Fehlermeldung aus, aber beim Zugriff auf die nicht vorhandene Eigenschaft versagte die gesamte Funktionalität.