2 Von „number“ über Arrays bis „undefined“
Eines der zentralen Features von TypeScript ist die statische Typisierung von Variablen und Parametern. Doch welche Typen gibt es eigentlich? Und wie werden sie eingesetzt? Diese Kapitel zeigt neben klassischen Typen wie string, number und boolean, wie Arrays, Tuples, Enums, Union-Typen und der any-Typ eingesetzt werden. Dabei dürfen natürlich die beiden aus JavaScript bekannten Typen undefined und null nicht fehlen, da sie die Quelle vieler Fehler in JavaScript darstellen. Neben all den Typen zeigt dieses Kapitel auch, wie der TypeScript-Compiler Typen automatisch erkennen kann und wie er mit so genannten „Type Assertions“ auch Tipps vom Entwickler entgegennimmt.
Der wohl einfachste in TypeScript verfügbare Typ ist boolean. Eine Variable vom Typ boolean kann die Werte true oder false annehmen: let isVisible: boolean = true;. Wie in der Zeile zu sehen ist, wird der Typ nach dem Variablennamen angegeben. Dabei trennt ein Doppelpunkt Variablenname und -typ. Diese Syntax mit dem Doppelpunkt wird von TypeScript durchgängig zum Angeben von Typen verwendet, sei es bei Variablendeklarationen oder bei Methodenparametern. Die Angabe des Typs wird auch als Type Annotation bezeichnet.
Hinweis
Mit ES2015 wurden die neuen Schlüsselwörter let und const eingeführt, die zum Deklarieren von Variablen und Konstanten genutzt werden. Vor ES2015 gab es in JavaScript das var-Schlüsselwort, das natürlich immer noch vorhanden ist. Variablen mit dem var-Schlüsselwort sind funktionsweit sichtbar, auch wenn sie beispielsweise innerhalb eines if-Blocks erstellt wurden. Dieses Verhalten widerspricht allem, was C#- und Java-Entwickler gewohnt sind. Und genau an dieser Stelle eilen let und const zur Hilfe. Mit let und const deklarierte Variablen sind nicht funktionsweit sichtbar, sondern nur in dem Block, in dem sie deklariert wurden. Das entspricht genau dem Verhalten von Variablen in C# und Java. Und es entspricht auch dem Verhalten, das die meisten Entwickler als „normal“ bezeichnen. Somit sollten in TypeScript Variablen nur mit let und const deklariert werden, nicht jedoch mit var.
Wenn eine Variable mit einem Typ wie boolean erstellt wurde, lassen sich danach keine anderen Werte mehr zuweisen, die nicht diesem Typ entsprechen. Wird beispielsweise einer boolean-Variablen ein String zugewiesen, führt das zu einem Compile-Fehler:
let isVisible: boolean = true;
isVisible = "hidden"; // Error
Typen erkennen
Der TypeScript-Compiler erkennt Typen automatisch, falls ihm das möglich ist. Eine Type Annotation ist somit in vielen Fällen überhaupt nicht erforderlich. Folgende isVisible-Variable ist beispielsweise auch vom Typ boolean, obwohl auf der Variablen kein Typ angegeben wurde:
let isVisible = true;
isVisible = "hidden"; // Error
Der TypeScript-Compiler erkennt aufgrund der Zuweisung des Werts true automatisch, dass die isVisible-Variable vom Typ boolean sein muss. Wird folglich später ein String zugewiesen, führt das zu einem Compile-Fehler. Vorsicht ist jedoch geboten, wenn Deklaration und Zuweisung auf zwei Anweisungen aufgeteilt werden. Dann kann der Compiler den Typ natürlich nicht mehr ermitteln, was im nachstehenden Listing der Fall ist. Die isVisible-Variable wird deklariert, jedoch nicht initialisiert. Somit nimmt der TypeScript-Compiler den any-Typ an. Diesem Typ lässt sich etwas x-Beliebiges zuweisen, wie ein Boolean oder ein String:
let isVisible;
isVisible = true; // OK
isVisible = "hidden"; // OK
Soll die isVisible-Variable tatsächlich auf den Typ boolean beschränkt werden, ist er bei der Deklaration wie folgt anzugeben:
let isVisible: boolean;
isVisible = true; // OK
isVisible = "hidden"; // OK
Das in diesem Abschnitt beschriebene Erkennen von Typen wird auch als Type Inference bezeichnet. Die Type Inference funktioniert natürlich nicht nur für den Typ boolean, sondern für jeden x-beliebigen Typ. Wenn der TypeScript-Compiler den Typ einer Variable erkennen kann, dann nutzt er ihn auch.
Zahlen
Zahlen in TypeScript sind vom Typ number, wie hier dargestellt: let width: number = 2; Da TypeScript eine Obermenge zu JavaScript darstellt, gibt es, wie auch in JavaScript, keine verschiedenen Typen für Zahlen wie int, float, double oder long. In JavaScript und so auch in TypeScript sind alle Zahlen 64-Bit-Fließkommazahlen. Einer number-Variablen in TypeScript lassen sich nicht nur Ganzzahlen zuweisen, sondern auch Zahlen mit Nachkommastellen: let width: number = 2.54;
String
Um in TypeScript Zeichenketten zu erstellen, wird der Typ string verwendet. Wie in JavaScript lassen sich Strings in einfachen oder in doppelten Anführungszeichen erstellen:
let firstName: string = "Thomas";
firstName = 'Tom';
TypeScript unterstützt auch die mit ES2015 eingeführten Template-Strings. Diese verwenden anstelle der Anführungszeichen so genannte Backticks. In einem Template-String lassen sich dann Ausdrücke unterbringen, indem ein Dollarzeichen gefolgt von einem geschweiften Klammernpaar platziert wird. Das folgende Listing zeigt einen Template-String, in dem die firstName-Variable verwendet wird:
let firstName: string ="Thomas";
let message: string = `Hallo ${firstName}, alles klar?`;
Neben Ausdrücken unterstützen Template-Strings auch Zeilenumbrüche, wie in Listing 2.1 zu sehen.
let message: string = `Welcome ${firstName},
how are you?`;
Listing 2.1
Einer der Vorteile von TypeScript ist es, dass sich TypeScript-Code in verschiedene JavaScript-Versionen kompilieren lässt, wie im ersten Kapitel gezeigt. Wird der Code aus Listing 2.1 in ES5 oder ES3 kompiliert, sieht das Ergebnis folgendermaßen aus:
var message = "Welcome " + firstName + ", \nhow are you?";
Wie gut zu sehen ist, werden der String und der Inhalt der firstName-Variablen konkateniert. Zudem enthält der String den Wert \n, was zu einem Zeilenumbruch führt. Wird der TypeScript-Code aus Listing 2.1 nach ES2015 kompiliert, erhält man das in Listing 2.2 dargestellte Ergebnis. Template-Strings sind nativer Bestandteil von ES2015. Somit sieht der JavaScript-Code aus Listing 2.2 genau gleich aus wie der TypeScript-Code aus Listing 2.1. Lediglich die String-Annotation auf der message-Variablen fehlt in Listing 2.2.
let message = `Welcome ${firstName},
how are you?`;
Listing 2.2
Arrays
TypeScript unterstützt Arrays, wie auch JavaScript das tut. Um eine Array-Variable zu erstellen, wird nach dem Typ noch ein eckiges Klammernpaar angegeben. Folgende Anweisung deklariert eine firstNames-Variable vom Typ string-array. Das zugewiesene Array enthält drei Strings:
let firstnames: string[] = ["Thomas", "Sara", "Julia"];
Neben dem eckigen Klammernpaar besitzt TypeScript noch eine andere Option, um ein Array zu erstellen: Die generische Array<T>-Klasse. Die folgende Anweisung erstellt ebenfalls eine firstNames-Variable vom Typ string-array und initialisiert sie mit einem string-Array mit drei Werten:
let firstnames: Array<string> = ["Thomas", "Sara", "Julia"];
Ob zum Deklarieren eines Arrays das eckige Klammernpaar oder die generische Array<T>-Klasse verwendet wird, macht keinen Unterschied. Was verwendet wird, hängt rein vom persönlichen Geschmack des Entwicklers ab.
Arrays durchlaufen
Zum Durchlaufen von Arrays besitzt TypeScript die mit ES2015 eingeführte for-of-Schleife. Listing 2.3 zeigt, wie sie eingesetzt wird. Das firstnames-Array wird mithilfe einer for-of-Schleife durchlaufen und die im Array enthaltenen Strings an der Konsole des Browsers ausgegeben.
let firstnames: string[] = ["Julia", "Anna", "Thomas"];
for (let firstname of firstnames) {
console.log(firstname);
}
Listing 2.3
Wird der TypeScript-Code aus Listing 2.3 nach ES2015 kompiliert, sieht die for-of-Schleife im generierten JavaScript-Code genau wie in Listing 2.3 aus. Wird der TypeScript-Code aus Listing 2.3 nach ES5 kompiliert, erstellt der TypeScript-Compiler im generierten JavaScript-Code eine klassische for-Schleife.
Neben der for-of-Schleife gibt es in TypeScript auch die for-in-Schleife. Diese gibt nicht die Werte des Arrays, sondern die Indizes zurück. Diese Funktionalität wird in Listing 2.4 genutzt. Das...