Dinge finden
Bisher hat das Hauptprogramm die Gegenstände über ihre Position im Array ausgewählt. Das ist anfällig: Wird am Anfang des Inventars ein Gegenstand hinzugefügt, ist kira.inventar[0] plötzlich etwas anderes. Besser ist es, einen Gegenstand über seinen Namen zu suchen. Und eine Funktion, die etwas über den Namen findet, ist für mehr nützlich als für Gegenstände: Auch ein Held in einer Gruppe, ein Monster in einer Höhle oder ein Zauber in einem Buch haben Namen. Also wird es eine generische Funktion, wie in der Lektion „Generics“.
Der Typparameter T ist der Typ der Dinge im Array. Die Funktion braucht von ihnen nur eines, einen name, und das sagt die Einschränkung: T extends { name: string }. Ohne sie weiß TypeScript nicht, ob ein T überhaupt einen Namen hat: main.ts(63,36): error TS2339: Property 'name' does not exist on type 'T'.
Die Array-Methode find aus der Lektion „Unions und Eingrenzen“ gibt das erste Element zurück, für das die Funktion true zurückgibt, oder undefined, wenn es keins gibt. Die Funktion gibt also T | undefined zurück, und wer sie aufruft, muss beide Fälle behandeln. Ein anderes Beispiel, eine Funktion, die etwas mit einer bestimmten Stufe findet:
function findeNachStufe<T extends { stufe: number }>(dinge: T[], stufe: number): T | undefined {
return dinge.find(ding => ding.stufe === stufe);
}
const gruppe = [
{ name: "Bruno", stufe: 5 },
{ name: "Lena", stufe: 2 },
];
const auftraege = [
{ titel: "Ratten im Keller", stufe: 1 },
{ titel: "Die Trollhöhle", stufe: 5 },
];
const held = findeNachStufe(gruppe, 2);
console.log(held?.name);
const auftrag = findeNachStufe(auftraege, 3);
if (auftrag === undefined) {
console.log("Kein Auftrag für Stufe 3");
} else {
console.log(auftrag.titel);
}Das gibt aus:
Lena
Kein Auftrag für Stufe 3Eine Funktion funktioniert für Helden und Aufträge gleichermaßen, und das Ergebnis behält seinen vollen Typ: auftrag.titel ist in Ordnung, weil T dort der Typ eines Auftrags ist. Aber TypeScript erlaubt dir auftrag.titel erst nach der Prüfung auf undefined.
Das Hauptprogramm wird versuchen, drei Gegenstände über ihre Namen zu benutzen: den Trank, das Schwert und ein Drachenei, das Kira nicht hat. Eine for...of-Schleife kann ein Array durchgehen, das direkt in ihr steht: for (const name of ["Heiltrank", "Silberschwert", "Drachenei"]). Wenn du das, was findeNachName zurückgibt, ohne die Prüfung direkt an benutzeGegenstand übergibst, meldet TypeScript es:
main.ts(89,41): error TS2345: Argument of type 'Gegenstand | undefined' is not assignable to parameter of type 'Gegenstand'.
Type 'undefined' is not assignable to type 'Gegenstand'.So schreibst du es:
Anweisungen
- 1
Schreibe unter
benutzeGegenstandeine generische FunktionfindeNachName<T extends { name: string }>(dinge: T[], name: string): T | undefined, die mitfinddas erste Ding mit diesem Namen zurückgibt. - 2
Ersetze im Hauptprogramm die beiden Zeilen mit
benutzeGegenstanddurch einefor...of-Schleife über die Namen"Heiltrank","Silberschwert"und"Drachenei". Suche für jeden Namen mitfindeNachNameden Gegenstand in Kiras Inventar. Ist er nicht da, gibKira hat kein Dracheneiaus (der Name des Helden und der Name, nach dem du gesucht hast); andernfalls gib aus, wasbenutzeGegenstandzurückgibt. Das Programm endet so:Kira trinkt Heiltrank: Leben 50/50 Kira rüstet Silberschwert aus Kira hat kein Drachenei