DEV Community

Marco
Marco

Posted on • Originally published at blog.disane.dev

Warum du nur noch TypeScript nutzen solltest ☝️

JavaScript ist tot, lang lebe TypeScript! Wie TypeScript dich aktiv unterstützt besseren und zuverlässigeren Code zu schreiben, erkläre ich dir in diesem Artikel 🎉


JavaScript, vermutlich kennt es jeder der bereits in der Webentwicklung zutun hatte. Auch wird jeder die Schmerzen kennen, die JavaScript auslöst und noch viel mehr werden die Probleme von JavaScript kennen. In diesem Artikel möchte ich dir zeigen welche Probleme JavaScript hat, welches davon am größten ist und wie TypeScript dir helfen kann.

Das Dilemma vom Anfang an 🎂

JavaScript gibt es schon seit zig Jahren, um genau zu sein seit 1995 (wow, da war ich 8 Jahre alt 😐). Zu der Zeit suchte man Möglichkeiten, wie man Webseiten etwas dynamischer gestalten kann. Anfangs gab es kaum Standards und jeder Browser-Hersteller kochte so seine eigene Suppe. Ältere Entwickler werden noch den Clash zwischen Netscape und Internet Explorer vermutlich noch gut im Hinterkopf haben. Aber JavaScript entwickelte sich immer weiter und wurde auch immer populärer und umfangreicher. Die genaue Geschichte ist aber sehr gut bei Wikipedia belegt. Die ist tatsächlich auch recht interessant und zeigt auch auf, warum viele Java und JavaScript verwechseln beziehungsweise warum es JavaScript heißt.

JavaScript - WikipediaWikimedia Foundation, Inc.Contributors to Wikimedia projects

Das fundamentale Problem von JavaScript 🏗️

Nun hat JavaScript aber ein fundamentales "Problem". Der Code wird nicht, wie es zum Beispiel bei anderen Programmiersprachen der Fall ist, im Vorfeld kompiliert, sondern lediglich bei der Ausführung (Just-in-Time compilation).

Andere Sprachen können dir im Vorfeld schon sagen, wo es eventuelle Probleme in deinem Code gibt. Das geht bei JavaScript (wenn man vom normalem Standard ausgeht) nicht. Das liegt schlicht und ergreifend daran, dass JavaScript früher in simplen Texteditoren geschrieben wurde und es kaum bis gar keine brauchbare IDE dafür gab. Ich kann mich daran noch sehr gut erinnern, wie man im Notepad an Webseiten nächtelang geschraubt hat und Probleme, die eigentlich offensichtlich waren, schlichtweg einfach nicht gefunden hat.

Genau diese Vorabprüfung fehlt im JavaScript, bis heute und genau hier kommt TypeScript ins Spiel.

Wie genau kann mir denn TypeScript helfen? 🆘

Nun ja, das ist recht einfach. In JavaScript war eine Variable z.B. nicht an einen Datentyp gebunden. Du konntest da einfach alles reinprügeln, problemlos. Der nachfolgende Code soll einfach mal demonstrieren, was mit JavaScript möglich ist und warum es problematisch ist.

var x = 1;

if (x === 1) {
  var x = 2;

  console.log(x);
  // Expected output: 2
}

console.log(x);
// Expected output: 2

Enter fullscreen mode Exit fullscreen mode

Soweit so gut. Klappt auch erst einmal. Nun kommen aber Benutzereingaben ins Spiel oder externe Daten, dann kann es sein, dass xnicht mehr numerisch ist, sondern vielleicht nulloder sogar ein Array.

var x = [1,2,3,4,5]; // not a number anymore

if (x === 1) {
  var x = 2;

  console.log(x);
  // Expected output: 2
}

console.log(x);
// Expected output: 2

Enter fullscreen mode Exit fullscreen mode

Der obige Code würde in dem Falle nicht mal mehr trümmern und aussteigen, sondern er würde prüfen: (x === 1). Da ein Arrayaber nicht 1würde er einfach dann ohne die Anweisungen im ifweiter machen. Noch schlimmer wäre der Code:

// Working code
var str = "Text";

console.log(str.replace("x", "s")) // Expected output: "Test"

// fatal failing code
var str = 1;

console.log(str.replace("x", "s")); // Expected output: Total descruction
Enter fullscreen mode Exit fullscreen mode

Das Resultat wäre, dass das JavaScript eine unbehandelte Exception werfen würde und die weitere Ausführung einfach verweigert. Das Schlimme daran ist aber, dass das nicht nur bei dir zur Entwicklungszeit passiert, sondern auch jedem User der deine Anwendung nutzt. Im Zweifelsfall sieht er nicht einmal was genau das Problem ist, was das Debugging echt schwer macht.

Was genau ist da das Problem? 🤔

Das Problem ist, dass du in JavaScript nicht sicherstellen kannst (außer durch Prüfungen zur Laufzeit, die wiederum mehr Code produzieren würde, den du warten musst und der ggf. auch wieder potenziell Fehler verursachen kann), dass Variablen, Parameter von Methoden etc. nur bestimmte Datentypen annehmen können. Stichwort: Typisierung.

Genau da setzt TypeScript (grundlegend an) und versucht dieses Problem zu lösen, in dem es eine Typisierung auf JavaScript aufsetzt.

TypeScript to the rescue 🛟

TypeScript wurde von Microsoft ca. 2012 von Microsoft ins Leben gerufen um JavaScript-Entwicklern zu helfen, verlässlichen und effizienten Code zu schreiben und orientiert sich da an anderen Sprachen, die Ähnliche Konzepte vorweisen (C# als Beispiel).

Wichtig zu beachten ist aber, dass TypeScript keine eigene Programmiersprache ist. TypeScript ist lediglich eine Obermenge von JavaScript. Das heißt im Kern, dass jeder JavaScript-Code gleichzeitig gültiger TypeScript code ist, umgekehrt jedoch nicht.

Das hat den Vorteil, dass bestehender Code oder Bibliotheken recht schmerzfrei (teil)migriert werden können ohne (zumindest in der Theorie), die generelle Funktionalität zu beeinflussen. TypeScript bietet dabei viele Konzepte, wie man sie auch anderen höheren Sprachen kennt, an. Dazu zählen als Beispiel Typisierung, generische Typen, Interfaces, Typeninferenz und generelle Signaturen von Klassen, Variablen, Methoden etc.

In dem Artikel beschränken wir uns aber lediglich auf den Aspekt der Typisierung.

To compile or not to compile 🎭

TypeScript-Code wird nicht klassisch kompiliert, sondern transpiliert. Das heißt, dass aus unserem TypeScript beim Erzeugen der Anwendung wiederum gültiges JavaScript generiert wird, den die Browser verstehen können. Natives TypeScript können die Browser nämlich nicht. Das sieht man auch schon an den Dateiendungen. TypeScript-Dateien werden mit .tserzeugt und dann zu .jstranspiliert.

Ergo: TypeScript gibt es nur zur Entwicklungszeit.

Typisierung, was zur Hölle? 😈

Sie ist wichtig. Sehr wichtig. Ich selber habe auch jahrelang JavaScript programmiert und habe den Sinn dahinter nicht verstanden, warum man auf einmal JavaScript typisieren sollte. Doch die Vorteile liegen klar auf der Hand, die ich dir gerne mit dem nachfolgendem Code einfach demonstrieren will. Wenn wir uns den JavaScript-Code von oben nehmen und in ein TypeScript-Projekt packen, dann sieht man das recht schnell, dass der Code 1:1 kompatibel ist:

Das Problem ist aber nach wie vor das selbe. Nun kommt aber der Clou. Wir sagen nun, dass ximmer nur numerisch sein darf. Das können wir mit let x: number = 1;machen.

⚠️

Wenn du TypeScript nutzt, solltest du var aus deinem Wortschatz streichen. Var ist böse, weil es nicht angibt, ob die Variable mehrfach beschrieben werden darf (let) oder ob es sich dabei um eine Konstante handelt ( const).

Wenn wir nun x ein Array zuweisen, dann sehen wir was ziemlich cooles:

Unsere Entwicklungsumgebung sagt uns, dass hier etwas nicht stimmt und wir hier schauen müssen. Auch würde das Erstellen/Transpilieren der Anwendung hier abbrechen.

Das selbe Verhalten hätten wir auch mit unserem zweiten Code.

Auch würde er die doppelte Deklaration von var strdirekt monieren:

Was auch vollkommen richtig ist. In JavaScript ging das aber und führte auch da immer wieder zu Problemen.

nuclear explosion GIF

Damit siehst du schon bereits beim Entwickeln, dass du unter Umständen Probleme im Code hast, noch bevor deine Anwendung an den Benutzer geht. Das verschafft dir Sicherheit, Selbstbewusstsein, dass deine Anwendung grundlegend klappt und du kannst dir sicher sein, dass Runtime-Fehler sehr stark minimiert werden.

Was kann/sollte man noch alles typisieren? 🤩

Du kannst aber nicht nur Variablen mit Signaturen ausstatten, sondern auch Klassen, Methoden und sogar eigene Interfaces erstellen, mit dem du sicherstellen kannst, dass die Daten auch so kommen, wie du sie erwartest.

// Method signature
function add(left: number, right: number): number {
    return left + right;
}

// Classes
class Person {
    private name: string;
    private age: number;
    private salary: number;

    constructor(name: string, age: number, salary: number) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    toString(): string {
        return `${this.name} (${this.age}) (${this.salary})`; // As of version 1.4
    }
}
Enter fullscreen mode Exit fullscreen mode

Du kannst auch damit Typen mischen (Union-Types) und so verschiedene Arten der Typen komponieren:

function successor(n: number | bigint): number | bigint {
    return ++n
}
Enter fullscreen mode Exit fullscreen mode

Der Code würde nämlich jetzt für ndie Typen numberoder biginterwarten und diese auch so zurückgeben. Gibt es da Probleme, siehst du es auch.

Was du unbedingt nicht tun solltest! 😖

TypeScript bietet für viele verschiedene Dinge unterschiedliche Typen an.

Documentation - Everyday TypesThe language primitives.Everyday Types

Der Typ, den du am besten direkt wieder vergessen solltest, ist any. Any ist praktisch das TypeScript äquivalent zu keiner Typisierung. Damit sagst du TypeScript nur, dass auch dieser Typ alles sein kann und schon hast du die selben Probleme wie in JavaScript, jedoch aber in TypeScript. Genau das sagt auch die Doku von TypeScript:

You usually want to avoid this, though, because any isn’t type-checked. Use the compiler flag noImplicitAny to flag any implicit any as an error.

Prinzipiell wird man auch nie anybenötigen, denn alles (und damit meine ich wirklich alles) lässt sich typisieren. Entweder bieten verwendete Bibliotheken direkt Typen an oder du schreibst sie eben selbst.

Tu dir selbst einen Gefallen und nutze bitte niemals any. Es gibt keinen Grund dafür und wenn du dir unsicher bist, verwende unknown, dafür gibt es den Typ.

Video gif. A cute grey tabby cat sits on her haunches with her paws together as if begging. Text, "Please."

Fazit 🎉

Ich hoffe ich konnte dir damit schon einmal einen kleinen Einblick in TypeScript geben und dir aufzeigen, wie TypeScript dich aktiv dabei unterstützen kann, besseren und zuverlässigeren Code zu schreiben. Ich weiß, dass es am Anfang hinderlich erscheint, aber glaub mir, seit dem ich TypeScript verstanden habe und es aktiv lebe, möchte ich nichts anderes mehr haben.

Im nächsten Artikel über TypeScript möchte ich dir gerne zeigen, wie du mit Interfaces umgehst und wie generische Typen dir helfen, doppelten Code zu vermeiden.


If you like my posts, it would be nice if you follow my Blog for more tech stuff.

Top comments (8)

Collapse
 
lexlohr profile image
Alex Lohr

Ernsthaft, es gibt Gründe dafür und dagegen, Typescript zu verwenden. Für schnelle Prototypen macht es wenig Sinn. Bei Libraries, die an die Grenzen der Type Engine stoßen, sind handgeschriebene Typen oft besser, da das Checking aufgrund der Notwendigkeit, zu casten, keinen Wert hat.

ZL;NG: wenn TS mehr im Weg ist, als das es hilft, nimm' JS, ansonsten TS.

Collapse
 
erikpischel profile image
Erik Pischel

Dass JavaScript eine interpretierte Sprache / Skript-Sprache ist und keine kompilierte Sprache, liegt sicherlich nicht daran, dass früher Javascript-Programme in einfachen Texteditoren erstellt wurden. Wahrscheinlich liegt es unter anderem daran, dass JavaScript für die Ausführung im Browser entwickelt wurde, bei dem es eben keinen Kompilierungsschritt gibt.

Auch andere interpretierte Sprachen sind populär, allen voran Python.

Collapse
 
disane profile image
Marco

Ja zugegeben ist das etwas engstirnig geschrieben, ja.

Collapse
 
efpage profile image
Eckehard

Klassische Compiler tun noch ein bischen mehr als nur Typen prüfen. Das wichtigste: Sie müssen allen Code übersetzen können, dadurch tauchen viele Fehler bereits bei der Übersetzung auf, die in JS erst zur Laufzeit sichtbar werden. Aber sie erkennen z.B. auch, ob eine Variable nicht initialisiert wird oder ob ein Code nie aufgerufen wird. Und nicht zu vergessen: Sie beherrschen ein vernünftiges "Tree-Shaking". Wenn Typescript das mal alles gelernt hat und zudem noch direkt vom Browser verstanden wird können wir gerne noch mal drüber spechen. Im Moment wiegen für mich die Vorteile die Nachteile (z.B. den züsätzlichen Übersetzungsschritt) oft nicht auf.

So eine typlose Spache erlaubt ja auch einige ziemlich coole Konstruktionen, die bei strikter Typisierung gar nicht möglich wären. Klar muss man sich ein wenig umstellen und hier und da mal eine nachgelagerte Typ-Prüfung einbauen, aber damit gelingt es doch, ziemlich stbailen Code zu bauen.

Collapse
 
mrkbr profile image
Mario Kober

Die meisten Punkte sind für mich gute Gründe bei JS zu bleiben.

Collapse
 
disane profile image
Marco

Was genau stört dich denn an der Typen-Sicherheit? Die nimmt dir ja zumindest sehr viele Runtime-Fehler schon praktisch beim Entwickeln ab und stellt sicher, dass diese nicht passieren.

Wenn man sich auch tief genug mit TS auskennt, dann ist das auch kein zeitlicher Overhead, sondern nur minimal aufgetragen, spart dir aber hinten raus einiges an Zeit.

Kleine Anekdote dazu:
Ich habe beruflich mal ein Problem debugged in einer komplexen Business-Angular-Anwendung die wirklich sehr komplex verzahnt ist (nicht negativ) und da hatte ein Entwickler any genutzt. Das Problem habe ich aber erst, auf Grund der Komplexität, nach 3-4 Stunden debuggen gefunden. Eine Typisierung im Nachhinein war nur mit sehr viel Aufwand möglich, weil einiges davon abhing.

Alles in allem hat mich das 1-2 Arbeitstage gekostet. Den Fehler im Vorfeld abzufangen mit Typen hätte vielleicht im Flow eine Stunde mehr gekostet (wenn überhaupt).

Collapse
 
mrkbr profile image
Mario Kober

Ja meine JS Aufgaben sind zu trivial und ich hatte noch nie das Gefühl, man müsste mir etwas obendrüber entwickeln. Nicht kompilieren zu müssen, ist mir viel wert. Bin einfach nicht die TS Zielgruppe. Bin vom Ansatz eher die Keep it as simple as possible Fraktion.

Thread Thread
 
disane profile image
Marco • Edited

Valid point. Ich komme da zum Beispiel auch aus dem professionellen Umfeld (extrem komplexe Anwendung für Softwareunternehmen) und bin da etwas "biased", sehe aber die Vorteile die es für mich z.B. auch bei kleinen Projekten hat