Montag, 22. Juli 2013

TypeScript

Am Freitag dem 28. Juni fand ein TecDay in Tennenlohe statt. Mit den beiden Themen Single Responsibility mit Peter Krämer und TypeScript mit meiner Wenigkeit, gab es zwei Entwicklungsthemen. In diesem Beitrag möchte ich noch einmal den Vortrag um TypeScript zusammenfassen.

Hintergrund

In den letzten Jahren hat sich JavaScript als Skriptsprache für den Browser endgültig durchgesetzt. Neben den einheitlichen Standards der Browser-API durch das W3C oder die WHATWG, war vor allem die gesteigerte Ausführungsgeschwindigkeit von JavaScript durch neue Engines ausschlaggebend. Darüber hinaus steht dem Webentwickler bereits seit langer Zeit ein großes Ökosystem verschiedenster JavaScript-Bibliotheken für den täglichen Einsatz zur Verfügung.
Ein weiteres Indiz dafür dass JavaScript schon lange die Schmuddelecke verlassen hat, ist der Einsatz von JavaScript auf der Serverseite. Spätestens mit node.js oder der CouchDB feiert die Skriptsprache auch auf diesen Gebiet seine Erfolge.

Der Einsatz von JavaScript ist für Entwickler von stark typisierten Sprachen oder mit reinen objektorientierten Hintergrund nicht immer einfach. Durch JavaScripts Duck Typing ist es zur Entwicklungszeit nicht ohne weiteres möglich festzustellen von welchem Typ eine Variable ist, welche Member ein Objekt besitzt, oder welche Signatur eine Methode hat. Je nach eingesetzter IDE gibt es hierzu zwar Abhilfe, jedoch keine absolute Lösungen. Die IDE verhindert schließlich nicht, dass eine fehlerhafte Zuweisung oder Methodenaufruf kodiert werden kann.

Es gibt bereits bestehende Sprachen die versuchen JavaScript um bekannte, etablierte Konzepte zu erweitern (Objektorientierung, Typsicherheit, etc.). Dazu gehören zum Beispiel CoffeeScript, HaXe und Dart. Während CoffeeScript und HaXe genau wie TypeScript Transcompiler sind, also nach JavaScript kompilieren, ist Dart eine vollkommen neue Programmiersprache.
Ob bei der Webentwicklung nun weiter reines JavaScript eingesetzt wird, oder eine um Eigenschaften erweiterte Sprache wie CoffeeScript oder TypeScript eingesetzt werden soll, bleibt natürlich jedem selbst überlassen.

TypeScript bietet jedoch in seinem Einsatz einige Vorteile gegenüber reinem JavaScript. Neben der Typsicherheit zur Compilezeit, bietet TS auch die Möglichkeit objektorientiert mit Interfaces und Vererbung zu arbeiten. Auch Lambda-Expressions sind möglich und bieten eine elegante Möglichkeit anonyme Methoden zu definieren. Seit der Version 0.9 unterstützt TypeScript auch Generics mit Typeconstraints.
Ein weiteres Argument, zumindest für die Visual Studio-Entwickler, ist der sehr gute Support der Entwicklungsumgebung. Wie gewohnt bietet das Studio IntelliSense für in TypeScript geschriebenen Code an.

Sprache

Im Gegensatz zu einigen anderen Ersatz-Skriptsprachen für JavaScript, will TypeScript JS nicht ersetzen, sondern erweitern. Code der in JavaScript lauffähig ist, wird eins zu eins ohne Änderungen auch in TypeScript funktionieren und kompilieren. Alle zusätzlichen Eigenschaften der Sprache, z. B. Typisierung, Objektorientierung und Generics, können, müssen jedoch nicht, eingesetzt werden. TypeScript eignet sich daher besonders für eine sanfte Migration einer bestehenden Codebasis.

Zwar ist ein direkter Vergleich zwischen JavaScript und TypeScript nicht immer möglich und sinnvoll, jedoch sollen die Codebeispiele auf gisthub den Einsatz von TypeScript helfen die Unterschiede zu verdeutlichen. Alle Beispiele sind mit TypeScript-Compiler Output in JavaScript vorhanden. Die Beispiele wurden mit dem TypeScript Playground erstellt.

Debugging

TypeScript kann entweder im Browser gedebugged werden, oder im Visual Studio. Das Visual Studio erfordert für das Debugging jedoch einen Internet Explorer und einen lokalen IIS(-Express), integriert sich jedoch nahtlos ins Studio und kann wie gewohnt eingesetzt werden. Im Browser stehen zwei Optionen zur Auswahl. Das Debuggen mit oder ohne Mappingfiles. Standardmäßig erzeugt der TypeScript-Compiler eine Mapping-Datei für jede erzeugte JavaScript-Datei. Wenn der eingesetzte Browser in der Lage ist mit Mappingdateien zu arbeiten, kann direkt mit dem TypeScript-Code gearbeitet werden.
Als letzte Alternative steht immer das Debuggen des generierten JavaScript-Codes zur Verfügung. Der TypeScript Compiler erzeugt keine hochoptimierte Ausgabe, sodass sich Ähnlichkeiten zum eigentlichen TypeScript schnell wiederfinden lassen.

Definitionen

Während der Entwicklung mit JavaScript wird man auch hier früher oder später Bibliotheken einsetzen. Damit der TypeScript-Compiler auch für diese in JavaScript verfassten Bibliotheken Unterstützung anbieten kann, müssen entsprechende Definitionen eingebunden werden. Definitionen können am ehesten mit Header-Dateien aus C verglichen werden. Eine Definition enthält alle zur Verfügung stehenden Member, Funktionen, Objekte und Module einer Bibliothek. Ein großartiges Projekt von Boris Yankov auf GitHub, DefinitelyTyped, ist zur Zeit die beste Anlaufstelle um TypeScript-Definitionen zu allen großen Bibliotheken zu finden.

INFO Zur Zeit findet auf CodePlex auch eine Diskussion zum Thema Definitionen statt. Eventuell erwartet den TypeScript Entwickler von Morgen eine Definition-Registry nach dem Vorbild von npm oder nuget.

Definitionen werden im Quellcode mit /// <reference path="PFAD ZUR DEFINITIONSDATEI" /> eingebunden. Es ist Konvention dass Definitionen auf .d.ts enden. Natürlich können auch mehrere Definitionen in einer Datei eingebunden werden. Es ist lediglich zu beachten, dass Definitionen vor dem ersten eigentlichen TypeScript-Code eingebunden werden. Müssen besonders viele Definitionen eingebunden werden, so können auch reine Include-Files erstellt und eingebunden werden.

Eine Definition wird standardmäßig vom TypeScript-Compiler immer referenziert. Dies ist die lib.d.ts. Die Datei enthält bereits Definitionen über das DOM Modell, plus IE-Eigenheiten. TypeScript bietet jedoch auch die Möglichkeit durch Angabe eines Commandline-Switches diese Standarddefinition zu überschreiben.

Module

Früher oder später stellt sich die Frage wie der Code effizient strukturiert werden kann ohne dabei den Überblick zu verlieren. Der TypeScript-Compiler bietet die Option, den gesamten JavaScript-Code in eine Ausgabe zu kompilieren. Dies kann besonders dann nützlich sein wenn die Ladezeiten zusätzlicher Skripts durch die Netzwerklatenz minimiert werden soll. Nachteil ist natürlich, dass immer der gesamte Code an den Client gesendet und geladen wird.

In der JavaScript-Welt haben sich verschiedene Modulsysteme mit ihren passenden Module-Loadern entwickelt. Auf der Client-Seite gehört AMD (asynchronous module definition) zu den bekannteren Vertretern. Dazu wird meist require als Clientbibliothek eingesetzt. Auf der Serverseite (z. B. in node) hat sich CommonJS' Modulsystem etabliert.
Welchen Sinn Module haben können, steht auf der Seite von require beschrieben, sodass an dieser Stelle eine simple Wiederholung ausbleibt.
Neben CommonJS und AMD existieren noch weitere Module Loader (z. B. Dojo oder LABjs). TypeScript unterstützt jedoch nur CommonJS und AMD von Haus aus. Andere Module-Loader müssen explizit implementiert werden.

Ein Modul exportiert ein oder mehrere Member mit dem Schlüsselwort export. Anschließend kann das Modul mit der import alias = require('Pfad zur Moduldatei ohne Endung') Anweisung importiert werden. Ein Beispiel findet sich dazu gisthub.

Fazit

TypeScript stellt eine geeignete Alternative zur reinen JavaScript-Entwicklung dar. Die Migration von bestehenden Code auf TypeScript ist durch die Kompatibilität besonders komfortabel. Die zusätzlichen Spracheigenschaften von TypeScript erweitern JavaScript lediglich ohne das bestehende Verhalten von JS vollkommen über den Haufen zu werfen.

Ist TypeScript nun der JavaScript-Killer? Sicherlich nicht. JavaScript-Kenntnisse sollten auch bei der TypeScript-Entwicklung mitgebracht werden, da die Konzepte dynamische Typisierung, Duck Typing, und Prototypen genauso in TypeScript möglich sind. Darüber hinaus ist TypeScript noch relativ jung. Viele zusätzliche Spracheigenschaften werden erst in der kommenden Version 1.0 den notwendigen Feinschliff erhalten. Auch der Compiler verhält sich in bestimmten Szenarien noch etwas widerspenstig (zu unspezifische Fehlermeldung, bzw. Geschwindigkeit). Die Entwickler versprechen zumindest in den kommenden Versionen Abhilfe für diese Probleme.
Ob TypeScript auch in Zukunft noch einen Einsatzzweck haben wird, vor allem mit der kommenden ECMAScript Version 6, wird sich noch zeigen müssen. Ansonsten bleibt noch die Migration zurück auf JavaScript. Dazu kann im Übrigen sehr gut der vom TypeScript-Compiler erzeugte JavaScript-Code verwendet werden ;-)

Wenn Interesse an der Präsentation mit einem kleinen TypeScript-Demoprojekt besteht, reicht eine kurze E-Mail an meine Adresse. Ich werde die Präsentation und die Demo dann zeitnah zurückschicken.

In diesem Sinne, Viel Spaß!

0 Kommentare:

Kommentar veröffentlichen