Moderne Webentwicklung: Im Zusammenhang von Anfang an – Teil 4
Moderne Webentwicklung: Im Zusammenhang von Anfang an – Teil 4
JavaScript ist universell anwendbar und hat längst vielfältige Einsatzgebiete. Leider ist die Sprache in größeren Projekten nicht immer einfach zu handhaben. Typen muss man nicht angeben, und mit der Objektorientierung nimmt es JavaScript auch nicht so genau. TypeScript bietet Abhilfe. Komfort bei der Entwicklung und ein automatisches Übersetzen in JavaScript sind klare Vorteile.
Wenn Sie die ersten drei Teile unserer Artikelserie über Webentwicklung verfolgt haben, dann sind Sie mit den Basistechnologien HTML5, CSS3 und JavaScript schon gut vertraut. HTML5 dient demnach dazu, einer Webseite die passende Struktur zu geben. Das Design wird komplett nach CSS3 verlagert, und für die Funktionalität steht die Programmiersprache JavaScript zur Verfügung. Damit haben Sie dem Grunde nach alles zusammen, um moderne Webapplikationen zu erstellen, die im Client laufen. Je weiter Sie in diese Technologien einsteigen und je größer die Projekte werden, desto eher werden Sie feststellen, dass die Programmiersprache JavaScript zu einem Engpass bei der Strukturierung des Quellcodes werden kann. Es kann mitunter schwierig werden, sauberen Programmcode in JavaScript zu erzeugen; die Fehlersuche gestaltet sich oft aufwändig. Abhilfe verspricht der Einsatz der Programmiersprache TypeScript, die eine Obermenge von JavaScript ist und der Programmiersprache neue Konzepte und Möglichkeiten hinzufügt. Wir werden uns in diesem Teil der Artikelserie mit den Basics von TypeScript beschäftigen (Textkasten: „Moderne Webprogrammierung: Eine systematische Einführung“). Beginnen wir zunächst damit, zu klären, welche Vorzüge der Einsatz von TypeScript mit sich bringt und wo diese Sprache insbesondere eingesetzt wird.
Die Frage lässt sich schnell beantworten: TypeScript bildet eine Obermenge von JavaScript, erweitert also JavaScript um bestimmte Features. TypeScript ist eine von Microsoft entwickelte Programmiersprache. Im Jahr 2012 erfolgte die Veröffentlichung der ersten Version (0.8), seitdem wird TypeScript kontinuierlich weiterentwickelt. Eine Menge an JavaScript-Frameworks setzen heute auf die Verwendung von TypeScript, so zum Beispiel Angular 2 oder React. TypeScript erweitert JavaScript – darum auch der Name – hauptsächlich um eine optionale statische Typisierung zum Zeitpunkt der Kompilierung. Dazu gehören die folgenden Features:
strukturelle Typisierung
Typinferenz
Klassen, klassenbasierte Vererbung und Dekoratoren
Typparameter (Generics)
abstrakte Schnittstellentypen (Interface)
zusätzliche Typen: any, void, enums, tuple, Funktionstypen, Vereinigungstypen (Union), Kreuzungstypen (Intersection) und Aufzählungstypen (enum)
Mehrfachvererbung mit Mixins
Typaliase
Namensräume
Weniger Laufzeitfehler werden durch eine starke Typisierung erreicht. Allerdings macht TypeScript aus JavaScript keine statisch typisierte Sprache. Es ermöglicht lediglich eine starke Typisierung. Damit kann man Variablen und Methoden typisieren, muss es aber nicht. Verwendet man diesen Ansatz, dann können bestimmte Fehler bereits während der Programmierung aufgedeckt werden. TypeScript und JavaScript sind stets 100 % kompatibel zueinander, und es ist möglich, jede beliebige JavaScript-Bibliothek mit TypeScript zu verwenden. Mit anderen Worten: Gültiger JavaScript-Code ist automatisch gültiger TypeScript-Code, und JavaScript-Quelldateien können durch den TypeScript-Compiler verarbeitet werden.
TypeScript-Quellcode wird in JavaScript-Code übersetzt. In diesem Fall spricht man von Transpilieren (Abb. 1). Kommen wir jetzt dazu, die Systemvoraussetzungen zu schaffen, um mit TypeScript zu programmieren.
Abb. 1: Aus TypeScript wird JavaScript
Um mit TypeScript zu programmieren, müssen wir die Entwicklungsumgebung einrichten. Letztendlich muss der TypeScript-Quellcode in JavaScript übersetzt werden. Dazu ist ein TypeScript-Compiler notwendig. Der TypeScript-Compiler aus dem Hause Microsoft benötigt die Laufzeitumgebung Node.js (Textkasten: „Node. js und npm“). Node.js unterstützt eine Vielzahl von Betriebssystemen, die aktuelle LTS-Version können Sie von der Node.js-Webseite herunterladen. Die Installation ist wenig spektakulär; unter Microsoft Windows handelt es sich um ein gewöhnliches Installationsprogramm. Ist die Installation abgeschlossen, haben Sie so gleich den Paketmanager npm installiert.
Die erfolgreiche Installation können Sie auf der Kommandozeile mit node --version überprüfen. Sie erhalten eine Ausgabe zur aktuell installierten Version, in unserem Fall etwa die Version v10.15.0. Dass der Paketmanager npm mitinstalliert wurde, können Sie auch sogleich mit dem Kommando npm --version testen. Als Version wird uns 6.4.1 auf unserer Entwicklermaschine angezeigt. Jetzt geht es bereits um die Installation des TypeScript-Compilers. Wir installieren ihn mit der Befehlszeile npm install -g typescript global, d. h. wir setzen die entsprechende PATH-Umgebungsvariable. Das zugehörige Paket wird aus dem Internet automatisch heruntergeladen und installiert. Der Vorgang wird ebenso auf der Kommandozeile protokolliert und quittiert. Ob auch das korrekt gelaufen ist, lässt sich via tsc –version überprüfen. Wir erhalten den Hinweis, dass die aktuelle Version des TypeScript-Compilers, d. h. Version 3.2.2, installiert wurde. Damit ist die Installation des Compilers abgeschlossen und wir können Programme in TypeScript schreiben. Mit dem Kommando tsc filename.ts lässt sich eine TypeScript-Datei dann nach JavaScript übersetzen. Das können Sie an einem einfachen Beispiel prüfen. Benutzen Sie dazu den Code der einfachen Funktion ShowTime:
function ShowTime(toDayDate: Date) {
}
Dass es sich um TypeScript handelt, erkennen Sie daran, dass dem Parameter der Funktion toDayDate der Datentyp Date zugewiesen wurde. In JavaScript sind bekanntlich keine Datentypen anzugeben. Schreiben Sie diese Codezeile zum Beispiel in die Datei time.ts und legen Sie sie in ein beliebiges Verzeichnis Ihres Rechners ab. Danach rufen Sie den TypeScript-Compiler für die Übersetzung mit ts time.ts auf. Wenige Augenblicke später haben Sie im gleichen Verzeichnis eine weitere Datei namens time.js mit dem folgenden Inhalt:
function ShowTime(toDayDate) {
}
Wenig überraschend unterscheidet sich der Inhalt nur darin, dass der Datentyp für den Parameter toDayDate jetzt nicht mehr vorhanden ist. Wir haben damit jedoch die Funktion des TypeScript-Compilers geprüft. Auf der Webseite der Programmiersprache TypeScript finden Sie unter dem Menüpunkt Playground eine Testumgebung, um TypeScript-Quellcode live in JavaScript-Quellcode zu übersetzen. Probieren Sie es aus, wenn Sie damit noch keine Erfahrungen haben. Wir haben es ebenso getan, wie ein Blick in Abbildung 2 zeigt.
Abb. 2: Nutzen Sie den Playground
Bevor wir uns nun ausführlicher mit den Sprachmerkmalen von TypeScript beschäftigen, sehen wir uns noch an, wie wir den TypeScript-Compiler in unseren Editor einbinden. Der Vorteil: Wir wollen nicht jede einzelne TypeScript-Datei per Kommandozeile übersetzen. Dieser Vorgang sollte im Laufe der Programmierarbeit mehr oder weniger automatisch geschehen. Als Editor setzen wir Visual Studio Code ein. In anderen Editoren funktioniert das Einbinden von TypeScript aber auf ähnliche Weise.
Wir gehen jetzt davon aus, dass Sie die leichtgewichtige Entwicklungsumgebung Visual Studio Code verwenden und bereits installiert haben. Der Editor ist auf der Basis von Webtechnologien programmiert und steht für alle gängigen Betriebssysteme zur Verfügung. Legen Sie ein neues Projekt an, indem Sie lediglich ein Verzeichnis erstellen. Wir haben ein solches Verzeichnis passenderweise „HelloWorld“ genannt. Innerhalb von HelloWorld können Sie zum Beispiel eine rudimentäre Projektstruktur, bestehend aus einer HTML5-Datei (index.html), einem Ordner /src und einem Ordner /style erstellen. In /src kommen die Skriptdateien und in /style die CSS3-Dateien. Uns geht es jetzt jedoch ausschließlich um die Verarbeitung der TypeScript-Dateien zu JavaScript. Die TypeScript-Unterstützung von Visual Studio Code kann in zwei verschiedenen Modi arbeiten:
Datei-Scope: In diesem Modus werden TypeScript-Dateien, die im Visual Studio Code geöffnet werden, als unabhängige Einheiten behandelt. Solange eine Datei a.ts nicht explizit auf eine Datei b.ts verweist (entweder mit Referenzdirektiven oder externen Modulen), gibt es keinen gemeinsamen Projektkontext zwischen den beiden Dateien.
Explizites Projekt: Ein TypeScript-Projekt wird über eine tsconfig.json-Datei definiert. Das Vorhandensein einer solchen Datei in einem Verzeichnis zeigt an, dass das Verzeichnis die Wurzel eines TypeScript-Projekts ist. Die Datei selbst listet die Dateien des Projekts sowie Compileroptionen auf.
Gehen wir nun davon aus, dass Visual Studio Code im expliziten Projektmodus verwendet wird. Wir benötigen also eine Datei tsconfig.json. Die Datei hat folgenden Inhalt:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"sourceMap": true
}
}
Wir definieren die sogenannten Compileroptionen. Als Zielversion wird ECMA-Script Version 5 angegeben; die CommonJS-Module werden verarbeitet, und es soll eine sourceMap erstellt werden. Letztere Einstellung bedarf einer Erläuterung. Möchte man den TypeScript-Quellcode debuggen, muss zur Laufzeit eine zeilenweise Abbildung des JavaScript-Quellcodes zum TypeScript-Code hergestellt werden. Der Hintergrund ist, dass man zur Fehlersuche den jeweiligen Breakpoint im TypeScript-Quellcode setzt. Zur Laufzeit wird im Browser jedoch JavaScript ausgeführt. Um letztlich zu wissen, an welcher Stelle unterbrochen werden soll, muss eine Zuordnung erfolgen. Das geschieht auf der Basis der *.js.map-Datei.
Ist die Datei tsconfig.json im betreffenden Ordner angelegt und gespeichert, können Sie eine erste TypeScript-Datei anlegen. Machen wir das in Form einer HelloWorld.ts und packen wir dazu folgenden Inhalt in Form einer einfachen Klassendefinition hinein:
class Startup {
public static main(): number {
console.log('Hello World');
return 0;
}
}
Nun soll diese TypeScript-Datei nicht durch einen manuellen Compileraufruf in eine JavaScript-Datei überführt werden, sondern es soll auf der Basis eines Build-Prozesses geschehen. Deshalb haben wir auch die Datei tsconfig.json definiert. Rufen Sie dazu in Visual Studio Code den Menüpunkt Terminal | Run Build Task auf. Alternativ können Sie auch die Tastenkombination CTRL+SHIFT+B drücken. Sie bekommen die Auswahl zwischen tsc: build und tsc: watch (Abb. 3).
Abb. 3: Start des Build-Tasks in Visual Studio Code
tsc: build: Der TypeScript-Compiler erstellt auf der Basis der Datei tsconfig.json aus den TypeScript-Dateien die passenden JavaScript-Dateien und die sourceMap-Dateien, sofern es in den Optionen so eingestellt wurde.
tsc: watch: Der TypeScript-Compiler sucht nach Änderungen in den Dateien und erstellt bei Bedarf die JavaScript- und die sourceMap-Dateien neu.
Gleichgültig, für welche Version des Build-Tasks Sie sich entscheiden, Sie haben danach im Ordner_/src_ neben der ursprünglichen TypeScript-Datei auch die JavaScript- und die sourceMap-Dateien. Konkret liegen nun vor: HelloWorld.ts, HelloWorld.js.map, HelloWorld.js (Abb. 4).
Abb. 4: Der Build-Prozess wird durch die Datei „tsconfig.json“ gesteuert
Nach der Installation des TypeScript-Compilers und der Einbindung des Compilers in Visual Studio Code sind wir nun endgültig bereit, einen Streifzug durch die Features von TypeScript zu unternehmen.
Einer der entscheidenden Vorzüge der Verwendung von TypeScript gegenüber dem Einsatz von JavaScript ist die Möglichkeit, bei der Variablendefinition einen Datentyp explizit anzugeben. TypeScript kennt unterschiedliche Datentypen. Zu den primitiven Datentypen gehören Boolean, Number, String, null, undefined und symbol. Die Definition wird über das Schlüsselwort let eingeleitet. Das ergibt folgende eindeutige Schreibweise, wobei wir die Möglichkeit der Initialisierung gleich mitnutzen:
let steuersatz: number = 19;
let lastName: string = "Mueller";
let isOpen:Boolean = true;
Der Datentyp void wird verwendet, wenn man das Nichtvorhandensein eines Typs ausdrücken möchte, beispielsweise für Funktionen ohne Rückgabewert. Weiterhin kann man Arrays definieren, beispielsweise in der Form:
let list: number[] = [1, 2, 3];
oder in der generischen Variante:
let list: Array<number> = [1, 2, 3];
Ein Tupel definiert man über die folgende Syntax:
let tupel:[number, number];
Die Datentypen in einem Tupel können auch verschieden sein:
let tupel:[string, number];
Aufzählungstypen werden mittels enum in der folgenden Form definiert und verwendet:
enum Color {Red, Green, Blue}
let c: Color = Color.Green;
Müssen wir eine Variable definieren, deren Datentyp wir nicht kennen, dann verwenden wir den Datentyp any. Das kann zum Beispiel dann sinnvoll sein, wenn wir mit Bibliotheken von Drittanbietern arbeiten. In diesem Fall erfolgt die Typprüfung ausschließlich zur Laufzeit.
Die Basis für die nichtprimitiven Datentypen ist object. Hierüber kann man eigene Datentypen definieren, wobei man in der Kombination Schlüssel-/Wertpaar vorgeht. Die Wertzuweisung erfolgt jetzt über einen Doppelpunkt, und der Datentyp wird in geschweifte Klammern eingebunden. Die Elemente werden über Kommata voneinander getrennt. Ein einfaches Beispiel:
let myTyp = {
myStatus: true,
lastName: "Müller"
}
Das zweite wichtige Feature von TypeScript ist die Definition von Klassen. Sie haben im letzten Teil dieser Artikelserie erfahren, dass die Arbeit mit Klassen in JavaScript nicht unproblematisch ist, es wird auf das Konzept der Prototypen gesetzt.
Mit TypeScript ist eine Klassendefinition möglich, wie bei klassischen Programmiersprachen wie C# oder Java. Sehen wir uns das genauer an. Eine Klasse wird in TypeScript mit Hilfe des Schlüsselworts class definiert. Damit ergibt sich folgende Schreibweise:
class Person {
…
}
Für eine Klasse können wir Felder (Eigenschaften), Konstruktoren und Methoden definieren. Von einer Klasse kann man eine Subklasse ableiten (vererben), Objekte erzeugen und Sichtbarkeiten festlegen. Auch statische Klassenmitglieder können wir erzeugen, wie in Listing 1 zu sehen.
Listing 1: Klassendefinition am Beispiel in TypeScript
class Person {
static status: boolean = true;
// Felder
protected name: string;
protected lastname: string;
// Konstruktor
constructor(_name: string) {
this.name = _name;
}
// Methoden
check() {
// Code
}
print() {
// Code
}
}
let person1 = new Person("Klaus");
let person2 = new Person("Karl");
class Student extends Person {
// Felder
private nr: Number;
print() {
// Code
super.print();
}
}
Der im Listing dargestellte Quellcode wird Ihnen als erfahrener Programmierer schnell vertraut vorkommen:
Wir erstellen eine Klasse mit dem Namen Person.
Diese enthält ein statisches Feld status, der Datentyp ist boolean.
Zwei Felder mit den Bezeichnungen name und lastname werden definiert.
Der Konstruktor wird mit dem Parameter _name aufgerufen und initialisiert das Feld name.
Es werden die Methoden check() und print() definiert.
Von der Klasse person erstellen wir zwei Objekte person1 und person2 und initialisieren diese jeweils mit Hilfe einer Zeichenkette für das Feld name.
Die Klasse Student erweitert die Klasse Person. Alle Member der Oberklasse werden an die abgeleitete Klasse vererbt.
Der Klasse Student wird das private Feld nr mit dem Datentyp number hinzugefügt.
Die Methode print() wird in der Klasse Student überschrieben. Beim Überschreiben von Methoden muss man die Methode der Oberklasse mittels super aufrufen.
Im Beispiel haben wir an verschiedenen Stellen für die Member (Felder, Methoden) entsprechende Sichtbarkeiten festgelegt. TypeScript bietet die Optionen private, protected und public. private bedeutet, dass die betreffenden Member nur innerhalb der Klasse zugänglich sind, die diese Member definiert. Wenn man von außen versucht, auf einen solchen Member zuzugreifen, dann quittiert der Compiler das mit einem Fehler. Felder und Methoden mit der Sichtbarkeit protected sind innerhalb der Klasse sichtbar, in der diese definiert werden, sowie in abgeleiteten Klassen. Auf Member mit der Sichtbarkeit public kann man universell von außen zugreifen.
Wichtig: Gegenüber der üblichen Definition der Sichtbarkeit, zum Beispiel in C#, ist bei der Klassendefinition in TypeScript public der Standard. Wenn man also keine Angabe bezüglich public, protected oder private macht, ist der Member öffentlich (public) von außen erreichbar. Das ist auch der Grund dafür, dass man public – wie im Beispiel bei den Methoden check() und print() – weglassen kann. Es schadet aber auch nichts, public zusätzlich anzugeben. Dann hat man jederzeit für Klarheit gesorgt.
Wir finden, die Ausdrucksweise von TypeScript bezüglich der Definition von Klassen ist klar und verständlich. Das Ergebnis des TypeScript-Compilers ist bekanntermaßen JavaScript. Was bei obigem Beispiel dabei herauskommt, sehen Sie in Listing 2.
Listing 2: Der JavaScript-Quellcode zum TypeScript-Code aus Listing 1
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Person = /** @class */ (function () {
// Konstruktor
function Person(_name) {
this.name = _name;
}
// Methoden
Person.prototype.check = function () {
// Code
};
Person.prototype.print = function () {
// Code
};
Person.status = true;
return Person;
}());
var person1 = new Person("Klaus");
var person2 = new Person("Karl");
var Student = /** @class */ (function (_super) {
__extends(Student, _super);
function Student() {
return _super !== null && _super.apply(this, arguments) || this;
}
Student.prototype.print = function () {
// Code
_super.prototype.print.call(this);
};
return Student;
}(Person));
JavaScript-Kenner haben damit sicherlich kein Problem und hätten eine solche Klassendefinition ohne großes Zögern mit Hilfe der Prototypen sofort niedergeschrieben. Für Ein- und Umsteiger in die Webprogrammierung ist die Schreibweise von TypeScript jedoch deutlich kompakter und leichter zu verstehen. Das gilt insbesondere dann, wenn Sie von anderen Hochsprachen, wie beispielsweise C# oder Java, kommen.
Ein weiteres interessantes Feature von TypeScript ist die Möglichkeit, bei der Klassendefinition Interfaces zu berücksichtigen. Ein Interface wird mit Hilfe des Schlüsselworts interface deklariert. Zum Beispiel wird mit:
interface IABS {
Use();
}
das Interface IABS deklariert. Es enthält den Rumpf der Methode use(). Dieses Interface kann dann dazu genutzt werden, es bei einer Klassendefinition anzugeben, beispielsweise bei der Klasse car:
class car implements IABS {
use() {
// Code
}
}
Die Klasse car muss nun verpflichtend die Methode use() implementieren. Ist das nicht der Fall, wird es vom TypeScript-Compiler beanstandet.
Datentypen anzugeben und Klassen in einer kompakten Form zu definieren, sind die primären Vorzüge von TypeScript gegenüber JavaScript. Dennoch lohnt es sich, auch auf die anderen Sprachmerkmale zu schauen. Dazu gehören:
Namespaces: Ein Namespace ist eine Möglichkeit, den zugehörigen Code logisch zu gruppieren. Dies ist in TypeScript im Gegensatz zu JavaScript leichter möglich. Man kann damit den Gültigkeitsbereich von Variablen eindeutig begrenzen. Die Syntax sieht wie folgt aus:
namespace MyNamespace {
}
Module: Ein Modul dient der Organisation des Quellcodes. Man unterscheidet zwischen internen und externen Modulen. Interne Module kamen in früheren Versionen von TypeScript zum Einsatz. Sie wurden verwendet, um Klassen, Schnittstellen, Funktionen zu einer Einheit zu gruppieren. Diese logische Gruppierung wird in neueren Versionen von TypeScript besser mit namespace vorgenommen. Externe Module in TypeScript existieren, um die Abhängigkeiten zwischen mehreren externen .js-Dateien zu spezifizieren und zu laden. Wenn nur eine .js-Datei verwendet wird, sind externe Module nicht relevant. Traditionell wurde die Abhängigkeitsverwaltung zwischen den JavaScript-Dateien mit Hilfe von Browser-Skript-Tags (<script> … </script>) durchgeführt. Aber das ist nicht erweiterbar, und das Laden erfolgt nur linear. Externe Module werden jetzt einfach als Module bezeichnet. Variablen, Funktionen, Klassen usw., die in einem Modul deklariert werden, sind außerhalb des Moduls nicht sichtbar, es sei denn, sie werden explizit mittels export nach außen bekannt gemacht. Umgekehrt muss eine Variable, Funktion, Klasse, Schnittstelle usw., die von einem anderen Modul exportiert wurde, mit dem Schlüsselwort import einbezogen werden. Ein Beispiel: Gehen wir davon aus, dass wir ein Interface IABS mit der einzigen Methode use() haben. Dieses ist in einer Datei IABS.ts gespeichert. Das Interface möchten wir von außen im Rahmen eines Moduls zugänglich machen. Wir ergänzen das Schlüsselwort export:
// File: IABS.ts
export interface IABS {
use();
}
In einer zweiten Datei car.ts wird die Klasse car definiert. Diese möchte das Interface IABS nutzen. Dazu müssen wir es zunächst über einen import verfügbar machen:
// File car.ts
import ABS = require('IABS')
class car implements ABS.IABS{
use() {
}
}
Mittels Modulen können also Quellcodebestandteile über Dateigrenzen und mit unterschiedlichen Namensräumen (Namespaces) nutzbar gemacht werden.
Abschließend möchten wir die Vorteile von TypeScript gegenüber JavaScript nochmals herausstellen:
stetige und zügige Weiterentwicklung der Sprache
gute Wartbarkeit des entstehenden Quellcodes
verbesserte Produktivität, insbesondere bei großen Projekten
Unterstützung von Codenavigation in integrierten Entwicklungsumgebungen und Codeeditoren
Fehlervermeidung durch Typsystem
leichte und umfassende Werkzeugunterstützung, wie Auto Complete
Support von modernen Sprachfeatures, wie einfache Klassendefinition, Einsatz von Subklassen und Interfaces
Festlegung von Sichtbarkeiten, wie private, protected und public für Klassenmitglieder
Einsatz in modernen Frameworks wie Angular
JavaScript ist TypeScript, d. h. bestehenden und funktionierenden JavaScript-Code können Sie direkt innerhalb von TypeScript-Quelltext verwenden. Beide Sprachen stehen damit nicht in Konkurrenz, sondern TypeScript macht JavaScript besser handhabbar.
TypeScript dürfte vielen Entwicklern und in den meisten Projekten Vorteile bringen. Der Umweg über den TypeScript-Compiler wird durch den erhöhten Komfort während der Entwicklung, insbesondere die Typsicherheit, das leichtere Debugging und die kompaktere Schreibweise von Klassen, mehr als aufgehoben. Als erfahrene Entwickler klassischer Hochsprachen fällt uns der Umstieg daher auch weniger schwer.
Wichtig ist es, den Überblick nicht zu verlieren. Welche Technologien sind notwendig, um weitere Kompetenzen auf dem Weg zur modernen Webentwicklung, speziell im Frontend-Bereich, zu erwerben? Wie hängen die beschriebenen Basistechnologien und die Erweiterungen in Form von Frameworks, Package Manager, Methoden usw. zusammen? Mit welcher Technologie sollte ich einsteigen? Eine definitive Antwort darauf kann es nicht geben. Sinnvoll wäre es mit Sicherheit, das bereits Gelernte anhand von echten Praxisprojekten umzusetzen. Dazu benötigt es eine konkrete Anforderung, die man mit Hilfe einer Webapplikation realisieren möchte. Eine Basisstruktur für ein solches Minimalprojekt könnte aus einer bestimmten Anzahl von HTML5-Dateien, der zugehörigen Style-Definition in Form von CSS3 und der Applikationslogik bestehen. Hier muss man nicht erst mit JavaScript experimentieren, sondern man kann gleich komfortabel mit TypeScript beginnen. Mit anderen Worten: TypeScript ist durchaus auch lohnend außerhalb der großen Frameworks verwendbar.
Letztendlich kommt das vollständige Verständnis der Technologien erst, wenn man echte Probleme löst. Haben Sie diese Artikelserie bis zu diesem Punkt verfolgt, dann schlagen wir spätestens jetzt vor, mit der Übung zu beginnen. Stricken Sie Ihre erste eigene umfassende Webapplikation. Sie werden erstaunt sein, was man inzwischen alles mit Webtechnologien anstellen kann.
Jetzt haben wir uns mit allen essenziellen Basistechnologien beschäftigt. Neben HTML5, CSS3 und JavaScript ging es dieses Mal um TypeScript. TypeScript macht das ehemalig lediglich als Skriptsprache gedachte JavaScript typsicher und damit handhabbar für größere Projekte. Hier startet man nicht immer bei null, sondern setzt intensiv auf Frameworks. Davon gibt es im Moment mehr als genug, sodass es kaum gelingt, hier den Überblick zu behalten. Einige Frameworks verschwinden schneller von der Bildschirmfläche, als sie gekommen sind, andere haben sich im Laufe der Zeit und über viele Updates einen festen Platz in der Entwicklerwelt erarbeitet. Sie werden für vielfältige Arten von Webapplikationen eingesetzt und sind flexibel. Dazu zählen auf jeden Fall Angular, React und Vue.js. Der Einstieg und die Verwendung beschäftigen uns in der nächsten Ausgabe des Entwickler Magazins. Bis dahin bleibt viel zu üben. Packen Sie es an!