TypeScript
Die Programmiersprache TypeScript ist eine Erweiterung der dynamisch typisierten Programmiersprache JavaScript um ein statisches Typsystem. Dynamisch typisierte Programmiersprachen sind flexibler, aber dafür auch fehleranfälliger als statisch typisierte Programmiersprachen.
Kann man bei dynamisch typisierten Programmiersprachen den Code direkt durch einen Interpreter ausführen lassen, kommt bei statisch typisierten Programmiersprachen noch ein Kompilationsschritt hinzu. Dank Typinformationen kann der Compiler einige potenzielle Fehler bereits erkennen, bevor das Programm ausgeführt wird. Zudem helfen Typinformationen beim Verständnis des Programmcodes.
Bei der objektorientierten Programmierung werden neue Datentypen auf Basis bestehender Datentypen erstellt. Dank der statischen Typisierung sieht man auf den ersten Blick, aus welchen Datentypen ein neuer Datentyp zusammengesetzt ist.
TypeScript ist eine Obermenge von JavaScript, d.h. jedes JavaScript-Programm ist auch ein TypeScript-Programm, aber nicht umgekehrt.
Variablen und Konstanten
In modernem JavaScript werden Variablen mit dem Schlüsselwort let deklariert:
Dabei kann sich der Datentyp jeder Variable dynamisch an den jeweils zugewiesenen Wert anpassen:
Dies macht es aber schwer im Programmcode zu erkennen, welche Operationen auf einen Wert angewendet werden können, und welchen Effekt das hat:
Typannotationen
Darum führt TypeScript sogenannte Typannotationen ein, die nach dem Variablennamen und einem Doppelpunkt aufgeführt werden:
Dadurch ist es nicht möglich, einer Variablen unpassende Werte zuzuweisen:
Der Datentyp muss dabei nicht zwingend angegeben werden, denn der Compiler kann diesen anhand des zugewiesenen Wertes ermitteln (Typinferenz).
Konstanten
Eine Variable kann ihren Wert im Programmverlauf verändern:
Oftmals ist diese Veränderbarkeit nicht erwünscht, da sich bestimmte Werte im Programmverlauf nicht ändern dürfen. In diesem Falle deklariert man Konstanten mit dem const-Schlüsselwort:
Eine erneute Zuweisung würde zu einem Fehler führen:
In JavaScript und TypeScript sollen wann immer möglich Konstanten statt Variablen verwendet werden. So kann man direkt erkennen, welche Werte sich ändern werden und welche nicht.
Grundlegende Datentypen
Die bisher betrachteten Datentypen lauten:
string: eine Zeichenkettenumber: eine Zahl (mit oder ohne Nachkommastellen)boolean: ein Wahrheitswert (trueoderfalse)
Zeichenketten: Verkettung und Interpolation
Zeichenketten oder Strings können als Literalen (z.B. "hello") direkt hingeschrieben oder mithilfe von Programmlogik basierend auf bestehenden Zeichenketten aufgebaut werden.
Zum Verketten von Strings dient der Operator +:
Diese Syntax kann aber etwas umständlich werden, wenn man wie beim obigen Beispiel nur Leerzeichen zwischen einzelne Wörter einfügen möchte.
Mithilfe von String-Interpolation kann ein mit Backtics umfasster String als Template (Schablone) definiert werden. Werte innerhalb von ${} werden dann als Ausdrücke interpretiert. Das obige Beispiel kann folgendermassen vereinfacht werden:
Die Leerzeichen stehen nun in der String-Literalen.
Zahlen: Konvertierung von und zu Zeichenketten
Oftmals werden Zahlen als Zeichenketten angegeben (z.B. bei Benutzereingaben) oder müssen als Zeichenketten ausgegeben werden. Dadurch wird eine Konvertierung zwischen den beide Datentypen string und number nötig. Dabei unterscheidet man zwischen zwei Vorgängen:
- parsen: Eine Zeichenkette wird in eine Zahl umgewandelt, was scheitern kann.
- rendern: Eine Zahl wird in eine Zeichenkette umgewandelt, was immer gelingt.
Eine Zeichenkette kann als Ganz- oder als Fliesskommazahl geparsed werden:
Kann die Zeichenkette nicht in eine Zahl umgewandelt werden, erhält das Ergebnis den Wert NaN: not a number:
Die Umwandlung von einer Zahl zu einer Zeichenkette gelingt immer und kann bei Bedarf mit einer Rundung erfolgen:
Wahrheitswerte und logische Operatoren
Wahrheitswerte oder Booleans können nur true oder false sein. Der Datentyp boolean unterstützt folgende logische Operatoren:
!: Negation (logisches Nicht)&&: Konjunktion (logisches Und)||: Disjunktion (logisches Oder)
Mehr vom Gleichen: Arrays
Arrays erlauben das Abspeichern mehrerer Werte des gleichen Datentyps:
Man beachte, dass eine skalare Variable mit dem Typ string annotiert wird, während ein Array von Strings mit der Annotation string[] versehen ist. Die Werte des Arrays werden innerhalb von eckigen Klammern als Liste aufgeführt.
Eine alternative Notation für Arrays sieht folgendermassen aus:
Statt string[] (“string array”) kommt die generische Notation Array<string> (“array of strings”) zum Einsatz. Diese wird uns später im Modul im Zusammenhang mit Typparametern noch begegnen.
Funktionen
In TypeScript werden Funktionsparameter mit einer Typannotation versehen. Der Aufrufer muss dann Argumente der entsprechenden Datentypen übergeben:
Die Funktion repeat erwartet zwei Parameter vom Typ string bzw. number und gibt einen Wert vom Typ string zurück. Entsprechend muss sich der Aufrufer an diese Datentypen halten:
Beachte, dass message nicht mit einer Typannotation versehen worden ist. Dank des deklarierten Rückgabetyps von repeat kann der Compiler dies selber ermitteln.
Funktionsliteralen
JavaScript und TypeScript unterstützen eine weitere Form der Funktionsdeklaration:
Hierbei handelt es sich um eine sogenannte Funktionsliterale, die als eine Konstante abgespeichert wird. Vergleichen wir die Syntax der Deklaration:
Die obere Notation verlangt, dass jede Funktion einen eigenen Namen hat. Die untere Notation ermöglicht auch anonyme Funktionen, d.h. Funktionen ohne Namen, die dann beispielsweise als Funktionsparameter übergeben werden können.
Verzweigungen
Verzweigungen können in JavaScript und TypeScript mit den Schlüsselwörtern if und else sowie mit deren Kombination else if ausgedrückt werden:
Werden mehrere Bedingungen auf dem gleichen Ausdruck geprüft, kann dies mit switch/case kompakter formuliert werden:
Dabei ist zu beachten, dass die case-Blöcke explizit terminiert werden müssen: entweder mit return wie oben oder mit break wie im folgenden Beispiel:
Da die Funktion keinen Wert zurückgibt, ist sie mit dem Rückgabetyp void annotiert.
Schleifen
JavaScript und TypeScript kennen zwei grundlegende Arten von Schleifen: while und for.
while und do/while
Die while-Schleife kann kopf- oder fussgesteuert verwendet werden. Bei der kopfgesteuerten Variante wird die Bedingung oben geprüft:
Bei der fussgesteuerten Schleife wird die Bedingung unten geprüft:
Dadurch wird die fussgesteuerte Schleife immer mindestens einmal durchgeführt.
for, for/of, for/in
Betrachten wir folgende while-Schleife:
Diese verfügt über eine Initialisierung (capital = 5000), eine Bedingung (capital > 0) und eine Modifikation (capital -= rent). Als Seiteneffekt soll die Anzahl der Monate hochgezählt werden (months++).
Mit der for-Schleife kann die obige kopfgesteuerte Schleife folgendermassen vereinfacht werden:
Dabei ist zu beachten, dass die Variable capital nur innerhalb der Schleife existiert. Die Variable months, die ausserhalb der Schleife deklariert worden ist, existiert auch nach der Schleife noch.
Die Schleifenvariante for/of kommt bei Arrays zum Einsatz. Ein Array lässt sich grundsätzlich auch mit einer herkömmlichen for-Schleife durchiterieren:
Ausgabe:
Bequemer ist aber die Variante mit for/of, welche der Schleifenbariable direkt den Wert zuweist. Der Zugriff auf den Index ist dabei nicht mehr möglich:
Ausgabe:
Mithilfe von for/in kann man auf die Indizes zugreifen. Aber Vorsicht:
Ausgabe:
Die Variable i ist kein Index, sondern ein String! Der Arrayzugriff funktioniert damit trotzdem.