Aufgabe 03 - TypeScript-Katas
Lernziele
Abschnitt betitelt „Lernziele“- Du beschreibst Funktionen und Daten zügig und vollständig mit Annotationen,
interfaceund Union Types. - Du übersetzt Compiler-Meldungen in verständliche Sätze und erklärst damit, welchen Fehler TypeScript vor dem Programmlauf abgefangen hat.
- Du typisierst Daten unbekannter Form (
unknown) durch eine Prüfung, statt sie mitanyoderasnur zu behaupten. - Du drückst Fachregeln einer Aufgabenstellung als Typen aus, sodass der Compiler sie erzwingt.
Ausgangslage
Abschnitt betitelt „Ausgangslage“Im Karate ist eine Kata eine kurze, festgelegte Bewegungsfolge, die so oft wiederholt wird, bis sie ohne Nachdenken sitzt. Genau das ist hier das Ziel, nur mit Typen statt Tritten.
Bevor Asynchronität und Framework dazukommen, muss das Typisieren in die Finger: kurze, unabhängige Übungsstücke (Katas) rund um Funktionen, Interfaces und Union Types (siehe Kapitel JavaScript und TypeScript, Einheiten 1.5 und 1.6). Alle Katas landen in katas.ts, jede mit zwei Testaufrufen (console.assert).
Allgemein
Abschnitt betitelt „Allgemein“Projektordner anlegen siehe https://qiz.at/projektordner
- Lies vorher kurz https://qiz.at/assignmentsabgabe durch.
- Nur vollständige Abgaben (siehe https://qiz.at/rules) können positiv bewertet werden.
- Abgabe- und Testdetails siehe https://qiz.at/assignmentsabgabe
- Die Übung liegt als Unterordner
uebung-03in deinem Jahres-RepositorySJ26_27_4AHITM_SEW_<Benutzername>_exercises, eingerichtet wie in Aufgabe 01 (package.jsonmitdevundtypecheck,tsconfig.jsonausnpx tsc --init). Du arbeitest allein.
Wesentlich_überwiegend
Abschnitt betitelt „Wesentlich_überwiegend“Aufgabe
Abschnitt betitelt „Aufgabe“median(values: number[]): der Median der Liste. Sortiere eine Kopie, nicht das Original.initials(firstName, lastName): aus “Alex Muster” wird “A.M.”.interface Appointment(Titel, Beginn alsDate, Dauer in Minuten, optionaler Raum) undendOf(appointment): liefert den Endzeitpunkt alsDate.describeRoom(appointment): liefert den Raum oder"kein Raum reserviert". Pflicht:??, keinif.
Tipp: Liefert
medianbei[10, 9, 100]Unsinn, sortiert das Standard-sortTexte statt Zahlen. Es braucht eine Vergleichsfunktion(a, b) => a - b. Hatsorted[middle]den Typnumber | undefined, kommt das vonnoUncheckedIndexedAccess: Lass die Einstellung aktiv und entscheide, wasmedianbei einer leeren Liste liefert. Minuten addierst du übergetTime(), eine Minute sind60_000Millisekunden.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
katas.tsunter"strict": trueohne Fehler und ohneanykompiliert.- jede der vier Funktionen zwei grüne Testaufrufe hat.
medianeine Kopie numerisch sortiert und den Leer-Fall entscheidet.describeRoommit??und ohneifauskommt.
Wie unter Allgemein.
Wesentlich_vollständig
Abschnitt betitelt „Wesentlich_vollständig“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
describeInput(input: string | number): bei Strings die Länge, bei Zahlen das Vorzeichen. Probier zuerst aus, was ohnetypeof-Fallunterscheidung passiert, und notiere die Meldung als Kommentar.type Grade = 1 | 2 | 3 | 4 | 5undisPassing(grade: Grade). Notiere als Kommentar, was der Compiler beiisPassing(6)meldet, im Original und in eigenen Worten.- Leg
type-errors.tsin deinen Projektordner und prüfe mitnpm run typecheck. Die Datei enthält fünf Fehler. Schreib für jeden als Kommentar in die Datei: Meldung im Original, Übersetzung in einen verständlichen Satz, Behebung. Behebe danach jeden Fehler.
Tipp: Die Übersetzung ist der wichtigste Teil: Sie sagt, was nicht passt und warum, statt die Meldung Wort für Wort ins Deutsche zu übertragen. Prüf mit
npm run typecheck, nicht mitnpx tsc --noEmit type-errors.ts: Liegt einetsconfig.jsonim Ordner, brichttscmit einem Dateinamen auf der Kommandozeile ab.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
describeInputmittypeofeingrenzt und die Meldung ohne Fallunterscheidung notiert ist.- die Meldung zu
isPassing(6)im Original und in eigenen Worten dokumentiert ist. - alle fünf Fehler aus
type-errors.tsmit Originalmeldung, verständlicher Übersetzung und Behebung kommentiert sind und die Datei fehlerfrei kompiliert.
Wie unter Allgemein.
PlusPlus Aufgabe
Abschnitt betitelt „PlusPlus Aufgabe“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
overlaps(a, b): Überschneiden sich zwei Termine? Untersuche die Grenzfälle: Ende des einen = Beginn des anderen und ein Termin, der den anderen vollständig umschließt. Teste beide und begründe deine Entscheidung zum Fall “Ende = Beginn” als Kommentar.parseAppointment(raw: unknown): Appointment | null: Der Wert kommt ausJSON.parseund ist von unbekannter Form. Prüf ihn, bevor du ihn verwendest, und lieferenull, wenn die Form nicht stimmt. Notiere die Compiler-Meldung, die beim direkten Zugriff aufraw.titleerscheint.- Teste
parseAppointmentmit einem gültigen Termin und mit mindestens drei fehlerhaften Eingaben (fehlendes Feld, falscher Typ, ungültiges Datum).
Tipp: Zwei Zeiträume überschneiden sich, wenn jeder vor dem Ende des anderen beginnt.
raw.titlegeht nicht: Richtig so. Prüf zuersttypeof raw === "object" && raw !== null, danach jedes Feld einzeln mittypeof.new Date("2027-13-45")wirft keinen Fehler, sondern liefert einInvalid Date, prüfbar mitNumber.isNaN(date.getTime()). MitexactOptionalPropertyTypesheißtroom?“das Feld fehlt”, nicht “das Feld istundefined”.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
overlapsbeide Grenzfälle testet und die Entscheidung zu “Ende = Beginn” begründet ist.parseAppointmentObjekt,null, jedes Feld und die Gültigkeit des Datums prüft.- die Tests mit gültigen und fehlerhaften Eingaben grün sind und die Meldung zu
raw.titlenotiert ist.
Wie unter Allgemein.
MandalorianPlus Aufgabe
Abschnitt betitelt „MandalorianPlus Aufgabe“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
Modelliere das Sortiment der Schulkantine “Safi”, also Brötchen, Nudeln, Salat, Getränke, Joghurt und dergleichen, so, dass der Compiler die fachlichen Regeln erzwingt:
- Artikel haben Name und Preis, ihre Ernährungsart ist
"vegetarian" | "vegan" | "meat"(etwa Käsebrötchen vegetarisch, Schinkenbrötchen mit Fleisch, Apfelsaft vegan). Ein “Aktionsartikel des Tages” hat zusätzlich einen Wochentag ("monday" | ... | "friday"). - Schreib
vegetarianOnly(items)so, dass der Rückgabetyp Artikel mit Fleisch unmöglich macht. - Beweise die Erzwingung: Ein Testaufruf, der dem Ergebnis ein Schinkenbrötchen unterschieben will, muss ein Compile-Fehler sein. Dokumentiere ihn als Kommentar mit der Meldung.
- Beurteile in drei Sätzen: Welche fachliche Regel steckt jetzt im Typsystem statt in einer Laufzeitprüfung, und was ist der Gewinn?
Tipp: Ein eigener Union Type für die Ernährungsart hilft. Die Schreibweise für eigene Prüffunktionen (
item is VegetarianItem) steht im Kapitel im Abschnitt zuanyundunknown.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- der Rückgabetyp von
vegetarianOnlyFleisch ausschließt. - der Schmuggel-Versuch als Compile-Fehler mit Meldung belegt ist.
- die Beurteilung stichhaltig ist.
Wie unter Allgemein.
Wissenscheck
Abschnitt betitelt „Wissenscheck“- Warum sortiert
medianeine Kopie statt des übergebenen Arrays? - Wie erzwingt
string | numbereine Fallunterscheidung, und womit trifft man sie? - Was ist der Unterschied zwischen
type Grade = 1 | 2 | 3 | 4 | 5undnumbermit Laufzeitprüfung? - Wozu ein optionales Feld (
room?) stattroom: string | null? Nenn einen Unterschied. - Was bedeutet die Rückgabetyp-Schreibweise
item is VegetarianItem? - Warum verlangt ein Wert vom Typ
unknowneine Prüfung, bevor man ein Feld liest?
Zeit dafür
Abschnitt betitelt „Zeit dafür“Durchschnittlich bis Wesentlich_vollständig: ca. 100 min
Autoren
Abschnitt betitelt „Autoren“- Oliver Maurhart (MAO)
- Michael Gabriel (GAM)
CC-BY-SA