Im ersten Teil dieser Serie habe ich mich mit der JavaScript-Alternative TypeScript im Allgemeinen beschäftigt. Im zweiten Teil, dem TypeScript-Workshop, möchte ich Euch einen praktischen Einstieg in die Programmiersprache bieten.
Hierfür erstellen wir zusammen eine HTML5-Webseite und zeigen verschiedene Rechtecke animiert auf einem Canvas-Element an.
Was ist TypeScript?
TypeScript ist eine Programmiersprache von Microsoft, deren Compiler nach JavaScript kompiliert. Diese Sonderform eines Compilers bezeichnet man auch als Transpiler.
Die Sprache bietet Sprachkonstrukte, die in allen modernen Programmiersprachen zu finden sind und die über den Standard der Sprache JavaScript hinausgehen, wie beispielsweise Klassen, Interfaces, Vererbung, Module, anonyme Funktionen, Generics und eine statische Typisierung.
Mehr über die Vorteile der Sprache TypeScript könnt Ihr in meinem vorhergehenden Blog-Artikel „TypeScript als JavaScript-Alternative“ nachlesen.
Vorraussetzungen für den TypeScript-Workshop
Zur Realisierung unserer Demo benötigen wir die Entwicklungsumgebung PHPStorm, alternativ kann auch WebStorm aus der gleichen Entwicklerschmiede verwendet werden. Da der TypeScript-Compiler selbst auch in JavaScript programmiert ist, wird eine Installation von NodeJS benötigt.
Installationsanweisungen für NodeJS gibt es auf der offiziellen Webseite.
In PHPStorm muss anschließend unter Einstellungen > Sprachen und Frameworks > TypeScript sichergestellt werden, dass der Befehl für den Node-Interpreter angegeben ist (Abb. 1). Somit ist alles vorhanden, was PHPStorm zum Umgang mit TypeScript-Projekten benötigt.
1. Einrichten eines neuen Projekts
In unserem Dateisystem erstellen wir einen neuen Ordner beliebigen Ortes und Namens, den wir dann in PHPStorm via Datei > Verzeichnis öffnen als neues Projekt öffnen.
2. Erstellen der HTML-Datei
In unserem Projektverzeichnis erstellen wir nun eine Datei index.html mit dem folgenden minimalem Inhalt:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> </head> <body> </body> </html>
Wir können diese Datei nun in einem Browser mit guten Developer Tools – beispielsweise Chrome – öffnen und darin alle Fortschritte unserer Entwicklung verfolgen.
Aktuell wird darin lediglich eine leere Seite ohne Titel angezeigt.
3. Erstellen der TypeScript-Konfigurationsdatei
Wir erstellen die Datei tsconfig.json mit dem folgenden Inhalt innerhalb unseres Projektverzeichnisses. Sie enthält alle wichtigen Informationen und Optionen für den TypeScript-Compiler. Zudem impliziert deren Präsenz PHPStorm, dass es sich bei dem Projekt um ein TypeScript-Projekt handelt.
{ "compileOnSave": true, "compilerOptions": { "outFile": "js/custom/Mfg.js", "noImplicitAny": true, "removeComments": true, "preserveConstEnums": true, "sourceMap": true }, "include": [ "src/**/*" ], "exclude": [ ] }
Im Abschnitt include wird angegeben, wo sich die TypeScript-Quelldateien befinden, die vom TypeScript-Compiler kompilieren werden sollen.
Die Compiler-Option outFile legt fest, dass das gesamte Kompilat innerhalb einer einzigen JavaScript-Datei zusammengefasst wird.
Alle in dieser Konfigurationsdatei angegebenen Pfade verstehen sich relativ zur tsconfig.json.
Wird in der tsconfig.json kein explizites Ausgabeformat angegeben, so kompiliert der Compiler standardmäßig in das Zielformat JavaScript ES3 Standard.
[smartblock id=6354]4. Programmieren der ersten TypeScript-Quelldatei
Da wir unserer tsconfig.json angegeben haben, alle TypeScript-Quellcodes unterhalb des Ordners src/ zu erstellen, legen wir diesen Ordner nun innerhalb unseres Projektverzeichnisses an. Wir wollen im späteren Verlauf unseres Workshops hier auch externe Bibliotheken zum Kompilieren ablegen – daher erzeugen wir nun einen weiteren Unterordner src/custom/, in dem wir all unsere eigenen TypeScript-Quellcodes ablegen werden.
Wir erstellen unsere erste TypeScript-Datei src/custom/Mfg.ts und definieren als deren einzigen Inhalt ein simples JavaScript-Statement:
alert("Mfg.ts");
5. Aktivieren des TypeScript-Compilers
PHPStorm fragt uns bereits beim Ersteller der ersten Quelldatei, ob wir den TypeScript-Compiler für dieses Projekt aktivieren wollen. Falls wir diese Entscheidung zu diesem Zeitpunkt noch nicht bestätigen wollen, kann die Aktivierung des TypeScript-Compilers zu einem späteren Zeitpunkt unter Einstellungen > Sprachen und Frameworks > TypeScript > TypeScript Compiler aktivieren nachgeholt werden (Abb. 2).
Wie in unserer tsconfig.json festgelegt, wurden all unsere TypeScript-Quellcodes nun zu einer einzigen Datei js/custom/Mfg.js kompiliert. Sollte uns PHPStorm diesen neu generierten Ordner nicht unverzüglich in unserem Projektfenster anzeigen, so kann der Fokus im Projektfenster auf unseren Projektordner gesetzt und der Menübefehl Datei > Synchronisieren verwendet werden.
6. Einbinden des Kompilats in unsere Webseite
Damit dieser JavaScript-Quellcode nun auch auf unserer Webseite ausgeführt wird, müssen wir diese Skriptdatei noch in unsere HTML-Seite inkludieren. Dies erfolgt über den Einbau des folgenden Script
-Tags in den Kopf unserer HTML-Seite:
<script type="text/javascript" src="js/custom/Mfg.js"></script>
Beim erneuten Laden unserer Webseite im Browser wird nun unser erstellter JavaScript-Alert zu sehen sein (Abb. 3).
7. Nutzen der Meldungen des TypeScript-Compilers
Bei jedem Speichern einer TypeScript-Datei kompiliert der TypeScript-Compiler alle TypeScript-Quellcodes selbstständig neu. Der Status sowie mögliche Fehlermeldungen des Compilers werden in dem separaten Fenster TypeScript in PHPStorm angezeigt (Abb. 4). Bei Eingabe eines ungültigen Funktionsaufrufs in unserer Quellcode-Datei wird uns dieses Fenster somit unverzüglich auf diesen Fehler hinweisen.
8. Erstellen von TypeScript-Klassen
Das testweise alert
-Statement können wir nun wieder aus der Datei src/custom/Mfg.ts entfernen. Stattdessen wollen wir in dieser Datei nun unsere erste TypeScript-Klasse Mfg
definieren. Die Syntax ist hierfür identisch zu denen anderer Hochsprachen:
/** * The main class containing the point of entry. */ class Mfg { }
Mfg
soll übrigens als Kürzel für „MayFlowerGame“ fungieren und künftig als Präfix für all unsere eigens erstellten Klassen dienen.
Beim Betrachten des Kompilats wird bereits jetzt deutlich, dass die entsprechende Funktionalität unter Verwendung reiner JavaScript-Syntax wesentlich schwieriger lesbar erscheint:
var Mfg = (function () { function Mfg() { } return Mfg; }());
9. Erstellen statischer Methoden
Als Einstiegspunkt unserer Applikation wollen wir eine statische Methode erstellen, die wir von außerhalb der Klasse aufrufen können. Bei TypeScript können wir für alle Methoden explizit den Rückgabetyp angeben; da die Methode in unserem Fall nichts zurückgibt, setzen wir als Rückgabewert den Typ void ein:
/** * The main class containing the point of entry. */ class Mfg { /** * The application's point of entry. */ public static main():void { } }
Da diese statische Methode den Einstiegspunkt in unsere Applikation darstellen soll, müssen wir sie von außerhalb der Klasse aufrufen. Hierfür bietet sich an, das JavaScript-Event window.onload
zu nutzen, da dieses ausgelöst wird, sobald alle Komponenten unserer Webseite fertig geladen wurden. Daher weisen wir diesem Event eine globale und konventionelle JavaScript-Funktion zu:
... /** * Being invoked when the application starts. */ window.onload = function() { Mfg.main(); };
10. Aufrufen bestehender JavaScript-Funktionen
In all unseren TypeScript-Codes ist es weiterhin erlaubt, reinen JavaScript-Code zu formulieren, der nach wie vor dynamisch typisiert wird. Als Beispiel definieren wir eine weitere statische Methode innerhalb unserer Klasse Mfg
, die den Titel unserer Webseite dynamisch setzt, und rufen sie in unserer statischen main
-Methode auf.
Beim Zugriff auf statische Methoden oder Felder muss unter TypeScript immer der Klassenname mit angegeben werden, auch wenn der Zugriff innerhalb der selben Klasse erfolgt. Somit grenzen sich statische Methodenaufrufe auch klar von JavaScript-Funktionsaufrufen ab.
/** * The main class containing the point of entry. */ class Mfg { /** * The application's point of entry. */ public static main():void { Mfg.setDocumentTitle(); } /** * Dynamically sets the document's title. */ private static setDocumentTitle():void { document.title = "TypeScript Minimal Primer, (c) 2017 Mayflower GmbH, v. 1.0"; } ...
Ein Refresh unserer Webseite im Browser zeigt uns den Effekt dieser Änderung: Ab sofort wird der Titel der Webseite im Browserfenster bzw. im Tab des Browsers angezeigt (Abb. 5).
11. Typisierung von Variablen
Alle Variablen – sowohl lokale Variablen als auch statische und nicht-statische Felder – können unter TypeScript mit einer statischen Typisierung versehen werden. Typisiert werden kann dabei auf eine abstrakte oder konkrete Klasse sowie auf einen der Typen boolean, number, string, void und any. Es existieren zudem noch ein paar spezielle Typen, die für uns hier und heute aber uninteressant sind.
Mit Hilfe der folgenden statischen Methode innerhalb unserer Klasse Mfg
können wir das Body
-Tag mit Style-Angaben versehen, und dabei die lokale Variable style
mit einer eindeutigen Klassenangabe typisieren:
/** * Dynamically applies css to the HTML body tag. */ private static styleHtmlBody():void { let style:CSSStyleDeclaration = document.body.style; style.backgroundColor = "grey"; style.textAlign = "center"; style.margin = "25px"; }
Auch diese statische Methode rufen wir aus unserer main
-Methode statisch auf:
/** * The application's point of entry. */ public static main():void { Mfg.setDocumentTitle(); Mfg.styleHtmlBody(); }
Diese Änderung hat nun den Effekt, dass der gesamte Hintergrund unserer Webseite grau wird (Abb. 6). Die restlichen Style-Attribute werden sich erst zu einem späteren Zeitpunkt bemerkbar machen.
12. Erstellen statischer Felder
Als nächstes wollen wir ein statisches Feld in unserer Klasse Mfg
erstellen. Wie für alle Variablen lässt sich hierfür der Datentyp genau angeben. Wir wollen in diesem Feld eine Instanz der Klasse MfgDemo
erstellen. Diese noch nicht existierende Klasse erstellen wir im nächsten Schritt.
Nach dem Hinzufügen des Feldes sollte das Fehlen dieser Klasse im Ausgabefenster des TypeScript-Compilers durch die Anzeige eines Fehlers deutlich gemacht werden.
/** * The main class containing the point of entry. */ class Mfg { /** The singleton instance of the demo. */ public static demo :MfgDemo = null; ...
13. Instanziieren von Klassen
Die neue Klasse MfgDemo
repräsentiert die eigentliche Demo und soll im Gegensatz zur Klasse Mfg
in einem reinen nicht-statischen Kontext betrieben werden. Wir legen sie unter src/custom/MfgDemo.ts an und statten sie mit einem Konstruktor und einer nicht-statischen init
-Methode aus:
/** * Handles the demo logic. */ class MfgDemo { /** * Creates a new demo logic. */ public constructor() { } /** * Inits this demo from scratch. */ public init():void { } }
Jetzt können wir in unserer Mfg.main()
eine Instanz der Klasse MfgDemo
erstellen und sie in unserer statischen Variable demo
speichern. Anschließend rufen wir die nicht-statische Methode init
unserer neu erstellten Instanz auf:
/** * The main class containing the point of entry and termination. */ class Mfg { /** The singleton instance of the demo. */ public static demo :MfgDemo = null; /** * The application's point of entry. */ public static main():void { Mfg.setDocumentTitle(); Mfg.styleHtmlBody(); Mfg.demo = new MfgDemo(); Mfg.demo.init(); } ... }
14. Verwendung nicht-statischer Felder und Methoden
Um unsere Zeichenfläche dynamisch zu erstellen und im Browser anzuzeigen, definieren wir in unserer Klasse MfgDemo
jetzt eine neue nicht-statische Methode initCanvas
und rufen sie innerhalb unserer nicht-statischen init
-Methode auf.
Das Canvas
-Tag wird nun dynamisch erstellt, mit einer Größe und Hintergrundfarbe versehen und anschließend an das Body
-Tag angehängt.
Für spätere Zugriffe auf das Canvas speichern wir den zugehörigen Rendering Context in einem nicht-statischen Feld ab:
/** * Handles the demo logic. */ class MfgDemo { /** The canvas rendering context for all 2D drawing operations. */ private canvasContext :CanvasRenderingContext2D = null; /** * Creates a new demo logic. */ public constructor() { } /** * Inits this demo from scratch. */ public init():void { this.initCanvas(); } /** * Inits the canvas and appends it to the HTML body element. */ private initCanvas():void { let canvasTag:HTMLCanvasElement = document.createElement("canvas"); canvasTag.width = 900; canvasTag.height = 500; canvasTag.style.backgroundColor = "white"; document.body.appendChild(canvasTag); this.canvasContext = canvasTag.getContext("2d"); } }
Anschließend bekommen wir im Browser unsere just hinzugefügte und leere Zeichenfläche angezeigt (Abb. 7).
Testweise können wir nach dem Festhalten des CanvasRenderingContext2D
eine Zeichenoperation absetzen, damit klar wird, wozu wir für spätere Zugriffe eine Referenz auf diesen Kontext festhalten:
... this.canvasContext = canvasTag.getContext("2d"); //perform a testwise drawing Operation onto the canvas context this.canvasContext.fillStyle = "red"; this.canvasContext.fillRect(10, 50, 100, 250);
Diese Zeichenoperation wird daraufhin auf unserem Canvas sichtbar (Abb. 8).
Im Anschluss kann diese testweise hinzugefügte Zeichenoperation auch wieder entfernt werden.
15. Definieren der Sichtbarkeit von Feldern und Methoden
Analog zu anderen Hochsprachen können auch unter TypeScript alle Felder und Methoden, egal ob statisch oder nicht-statisch, mit einem der drei Visibility-Modifier public, private oder protected versehen werden. Private Member sind dabei nur aus der selben Klasse aus ansprechbar, Protected Member nur aus der selben sowie aus abgeleiteten und Public Member aus allen Klassen heraus ansprechbar.
16. Nutzen von Arrays und Generics
Arrays bieten uns in TypeScript eine komfortable Möglichkeit, eine Sammlung von Objekten zu verwalten. Da wir im nächsten Schritt verschiedene Rechtecke auf unserer Zeichenfläche anzeigen wollen und sich diese in Position, Größe und Farbe unterscheiden sollen, bietet es sich an, eine eigene Klasse dafür zu definieren. Wir legen die neue Klasse MfgRect
unter src/custom/MfgRect.ts an. Diese Klasse enthält alle genannten Attribute sowie eine nicht-statische Methode zum Zeichnen des Rechtecks auf einem Canvas Rendering Context:
/** * A rectangular in 2D space. */ class MfgRect { /** The left coordinate. */ public x :number = 0; /** The top coordinate. */ public y :number = 0; /** The horizontal dimension. */ public width :number = 0; /** The vertical dimension. */ public height :number = 0; /** The fill color. */ public color :string = null; /** * Constructs a new rectangular in 2D space. * * @param x Left coordinate. * @param y Top coordinate. * @param width Horizontal dimension. * @param height Vertical dimension. * @param color Fill color. */ public constructor(x:number, y:number, width:number, height:number, color:string) { this.x = x; this.y = y; this.width = width; this.height = height; this.color = color; } /** * Fills a rect with the specified dimensions and color. * * @param ctx The rendering context. */ public draw(ctx:CanvasRenderingContext2D):void { ctx.fillStyle = this.color; ctx.fillRect( this.x, this.y, this.width, this.height ); } }
In unserer Klasse MfgDemo
wollen wir nun verschiedene Rechtecke erstellen und diese in einem typisierten Array ablegen. Hierfür definieren wir die nicht-statische Methode initRects
und rufen sie in unserer nicht-statischen init
-Methode auf. Das typisierte Array halten wir in dem nicht-statischen Feld rects
fest:
/** * Handles the demo logic. */ class MfgDemo { ... /** All rects to show in the demo. */ private items :Array<MfgRect> = null; /** * Creates a new demo logic. */ public constructor() { } /** * Inits this demo from scratch. */ public init():void { this.initCanvas(); this.initRects(); } ... /** * Inits all rects for this level. */ private initRects():void { this.items = [ new MfgRect(125, 25, 75, 75, "orange"), new MfgRect(300, 150, 120, 30, "yellow"), new MfgRect(550, 250, 30, 120, "red" ), new MfgRect(620, 75, 150, 50, "grey" ), ]; console.log("Created [" + this.items.length + "] rects."); } }
Durch den Logbefehl am Ende der nicht-statischen Methode initRects
wird die Anzahl der erstellten Rechtecke nun in der Konsole unseres Browsers angezeigt (Abb. 9).
17. Definieren von JavaScript-Callbacks
Statische TypeScript-Methoden sind als JavaScript-Callbacks problemlos nutzbar. Soll allerdings eine nicht-statische Methode als JavaScript-Callback verwendet werden, so muss diese mit einer speziellen Syntax versehen werden („Arrow Function“), damit der Kontext von this
beim Aufruf dieser nicht-statischen Methode nicht verloren geht.
Zum Nachstellen dieses Sachverhalts wollen wir in unserer nicht-statischen init
-Methode der Klasse MfgDemo
eine neue nicht-statische Methode startDemoLoop
aufrufen. Sie ruft alle zehn Millisekunden die nicht-statische Methode tick
auf.
Damit der Objektkontext innerhalb der nicht-statischen Methode tick
erhalten bleibt, muss die Signatur dieser nicht-statischen Methode die Arrow Syntax beinhalten:
/** * Handles the demo logic. */ class MfgDemo { ... /** * Inits this demo from scratch. */ public init():void { ... this.startDemoLoop(); } ... /** * Starts the endless demo loop. */ private startDemoLoop():void { window.setInterval(this.tick, 10); } /** * Handles one demo tick. */ private tick=()=> { console.log("tick: " + this.items); }; }
In der Konsole des Browsers wird nun this
als korrekte Instanz der Klasse MfgDemo
angezeigt.
Wird die Arrow-Syntax testweise weggelassen, so wird this
fälschlicherweise als Instanz des globalen Window-Kontexts interpretiert, sodass ein Zugriff auf das nicht-statische Feld items
an dieser Stelle scheitert und somit als undefined zurückgegeben wird!
18. Verwenden von Foreach-Schleifen
Hiermit können wir komfortabel über alle Elemente von Arrays und anderen Collections iterieren. Als Beispiel können wir die Position all unserer Rechtecke verändern und anschließend alle Rechtecke auf die Zeichenfläche zeichnen.
Wir rufen hierfür zwei separate, nicht-statische Methoden innerhalb unserer nicht-statischen Methode tick
auf. Der zuvor testweise eingesetzte Konsolenbefehl kann in diesem Schritt wieder entfernt werden.
/** * Handles the demo logic. */ class MfgDemo { ... /** * Handles one demo tick. */ private tick=()=> { this.render(); this.draw(); }; /** * Renders the current game tick. */ private render():void { for (let item of this.items) { item.y += 0.5; } } /** * Draws the current game tick. */ private draw():void { this.canvasContext.clearRect(0, 0, 900, 500); for (let item of this.items) { item.draw(this.canvasContext); } } }
Anschließend sehen wir unterschiedliche Rechtecke auf unserer Zeichenfläche, die allesamt langsam absteigen (Abb. 10).
19. Einbinden externer Bibliotheken
Zu guter Letzt wollen wir eine externe JavaScript-Bibliothek einbinden und in unserem Code typisiert verwenden.
In unserem Beispiel wollen wir die JavaScript-Bibliothek FPSMeter einbinden, mit der wir die Frames Per Second unserer Demo gemessen und angezeigt bekommen.
Bitte beachten!
Das manuelle Einbinden externer JavaScript-Bibliotheken und TypeScript Definition-Files ist deprecated! Die korrekte Einbindung externer Bibliotheken erfolgt durch den Einsatz des Node Package Managers. Das Herunterladen der JavaScript-Bibliothek und der zugehörigen Type-Definition-Dateien kann für die Erweiterung „FPSMeter“ beispielsweise mit Hilfe der folgenden Befehlen erfolgen:
npm init -f npm install fpsmeter npm install @types/fpsmeter
Da die Verwendung des Node Package Managers den Rahmen dieses Workshops an dieser Stelle sprengen würde, erfolgt die Einbindung in unserem Projekt daher manuell.
Die Einbindung einer externen Bibliothek erfolgt in drei Schritten:
19.1. Einbinden der JavaScript-Datei der Bibliothek
Die JavaScript-Datei der Erweiterung FPSMeter kann in vollständiger oder auch in minifizierter Version eingebunden werden. Die aktuelle Version der Bibliothek FPSMeter kann von der Webseite der Erweiterung heruntergeladen werden.
In unserer Demo legen wir die Datei unter js/lib/fpsmeter-0.3.1.min.js ab. Damit der Browser sie laden kann, müssen wir die Datei in unserer index.html referenzieren. Daher erweitern wir das Tag unserer Webseite um das folgende Script
-Tag:
<script type="text/javascript" src="js/lib/fpsmeter-0.3.1.min.js"></script>
19.2. Einbinden der Type-Definition-Datei der Bibliothek
Damit der TypeScript-Compiler die Typisierung der externen JavaScript-Bibliothek handhaben kann, muss eine sogenannte Type-Definition-Datei zu unseren zu kompilierenden TypeScript-Quellcodes hinzugefügt werden.
Die Seite definitelytyped.org versteht sich als Repository aller wichtigen Type-Definition-Dateien für alle wichtigen JavaScript-Bibliotheken. Für das FPSMeter befindet sich die entsprechende Type-Definition-Datei auf GitHub.
Wir können diese Datei an einem beliebigen Ort unterhalb unseres Verzeichnisses src/ ablegen, damit der TypeScript-Compiler die Struktur der Bibliothek erkennen kann. Unserem Schema im Dateisystem folgend sollte die Datei unter src/lib/FPSMeter.0.3.0.d.ts abgelegt werden.
19.3. Einbau der Erweiterung in den Code
Eine Instanz der Klasse FPSMeter
soll nun in unserer Klasse MfgDemo
in einem nicht-statisches Feld festgehalten werden. In unserer nicht-statischen Methode init
instanziieren wir die Klasse FPSMeter
, und in unserer nicht-statischen Methode tick
teilen wir dem FPS-Meter mit, wann der aktuelle Tick beginnt und wann er endet.
/** * Handles the demo logic. */ class MfgDemo { ... /** The FPS display. */ public fpsMeter :FPSMeter = null; ... /** * Inits this demo from scratch. */ public init():void { ... this.initFpsMeter(); ... } /** * Inits the external FPS Meter. */ private initFpsMeter():void { this.fpsMeter = new FPSMeter( null, { graph: 1, decimals: 1, position: "absolute", zIndex: 10, right: "5px", top: "auto", left: "auto", bottom: "5px", margin: "0", heat: 1 } ); } /** * Handles one demo tick. */ private tick=()=> { this.fpsMeter.tickStart(); this.render(); this.draw(); this.fpsMeter.tick(); }; }
Anschließend wird das FPS-Meter in der unteren rechten Ecke unserer Webseite angezeigt (Abb. 11).
Da wir einen konstanten Wert von 10ms als Verzögerung zwischen unseren Ticks definiert haben, sollte der FPS-Counter permanent 100 Frames pro Sekunde anzeigen. Interessanter wird die Verwendung dieser Erweiterung natürlich erst, wenn aufwändigere Rechen- und Zeichenoperationen – beispielsweise unter Verwendung einer 3D-Zeichenfläche – durchgeführt werden und somit ein Schwanken dieses FPS-Wertes beobachtet werden kann.
Abschluss
TypeScript stellt eine praktische Alternative zu JavaScript dar, mit der auch das Umschreiben bestehender JavaScript-Projekte nach TypeScript nahtlos möglich ist.
Ich möchte jedem Entwickler die Einführung von TypeScript sehr an Herz legen, da diese einen großen Gewinn für jedes JavaScript-Projekt darstellt.
Den Projektcode des TypeScript-Workshops findet man übrigens auf GitHub. Und wenn Du Dich noch tiefer mit dem Thema beschäftigen möchtest, findet am 27. Juni ein TypeScript-Workshop in Berlin statt.
Schreibe einen Kommentar