JSDoc

Statische Typisierung in JavaScript mit JSDoc

Von am 22.02.2022

JavaScript und der Mangel von Typen

Auf einer sehr abstrakten Ebene ist es das Ziel von allen Computer-programmen mit Daten zu arbeiten; sie zu lesen, verändern und wieder zu speichern oder weiter-zu-geben. Zu diesem Zweck besitzen alle modernen Programmiersprachen das Konzept von Datentypen, also Arten von Daten. Häufige Datentypen beinhalten verschiedene Arten von Zahlen, Wahrheitswerte, Zeichenketten, und Kombinationen von diesen, was oft als Objekte bezeichnet wird.

Über die Zeit hat sich ein System zur Typisierung von Daten entwickelt, dass sich “statische Typisierung” nennt, also, dass eine Speicherzelle, oder Variable, zum Zeitpunkt ihrer Initialisierung festlegen muss, welche Art von Daten in ihr gespeichert werden können. Üblicherweise verbieten IDEs dem Entwickler/Entwicklerin nicht kompatible Daten in eine Variable zu speichern. So können beispielsweise keine Zahlen in deine Variable die für Texte deklariert wurde gespeichert werden.

Hier ist JavaScript anders als der Großteil der gängigen Programmiersprachen. JavaScript ist dynamisch typisiert, es gibt also keine Garantien, dass der Inhalt einer Variable den selben Datentyp beinhaltet mit der sie initialisert worden ist. Tatsächlich haben JavaScript-Variablen überhaupt keine für den Programmierer/Programmiererin lesbare Typ-information.

Die einzige Möglichkeit den Typ einer Variable festzustellen ist ihren Wert zu lesen und mit anderen Werten zu vergleichen. JavaScript ermöglicht es außerdem noch mithilfe des “instanceOf” Operators, den Inhalt einer Variable mit einem der wenigen Datentypen (number, string, …) zu vergleichen um zu erfahren ob es sich bei der Variable um eine Instanz dieses Typs hält.

Obwohl dieses System von dynamischen Typen seine Vorteile hat, führt es in den meisten Fällen zu Fehlern die im Großteil von “Schlampigkeit” des Entwicklers/Entwicklerin stammen, die in anderen Programmiersprachen durch die statische Typisierung sowie Warnungen in der IDE ausgeglichen werden würde. Beispielsweise ist es in JavaScript ohne weiteres möglich einen String in eine Funktion zu schicken die eine Zahl als Input erwartet. Ob daraus Fehler entstehen weiß der Programmierer/Programmiererin erst sobal er/sie den Code ausführt.

Diese Typen-sicherheit ist der JavaScript Community so abgegangen, dass es mittlerweise eine eigene Programmiersprache names TypeScript gibt, die als Superset von JavaScript alle Features der Sprache übernimmt und noch statische Typisierung hinzufügt. Wer aber lieber in standard JavaScript bleiben und trotzdem statische Typisierung nutzen will hat auch Optionen. Beispielsweise JSDoc.

JSDoc und Pseudo-typisierung

JSDoc ist eine Markup-sprache, mit der sich Meta-informationen in JavaScript Code kodieren lassen. Die meisten modernen IDEs können diese Meta-information lesen um den Programmierer/Programmiererin beim Entwickeln zu unterstützen. Ein Beispiel:

/**
 * Das ist der beste String der Welt
 * @type {string}
 */
let s = "wow";

Mithilfe der /** … */ Syntax kann ein JSDoc Kommentar geschrieben werden. Der Kommentar oben beinhaltet eine kurze Beschreibung der Variable und, für uns wichtiger, deklariert auch den Typen der Variable als String. Mithilfe dieses Kommentars können wir nun die IDE informieren, dass die Variable nur Strings als Input akzeptieren soll. Beispielsweise wird für folgende Zeile eine Warnung angezeigt:

/**
 * Das ist der beste String der Welt
 * @type {string}
 */
let s = { text: "wow" }; // Warnung, weil ich ein Objekt in eine "String-variable" speichere

Es ist wichtig zu erwähnen, dass ich auch mit dem Fehler von oben in den meisten IDEs noch komplieren und testen kann. Der Kommentar hat keine Auswirkung auf mein Programm, er deklariert nur klar meine Intentionen und hilft der IDE mich zu warnen, falls ich etwas tue, dass diesen Intentionen widerspricht. Im Folgenden möchte ich nun noch ein paar weitere nützliche Features von JSDoc showcasen. Für mehr Info empfiehlt es sich die offiziele Dokumentation zu besuchen.

Funktions-inputs und Outputs definieren

JSDoc erlaubt es sehr genau zu definieren welche Art von Parametern in eine Funktion geschickt werden “dürfen” und welches Ergebnis daraus produziert wird. Hier ist ein Beispiel:

/**
 * Generiert einen Satz der das Alter "sagt"
 * @param {number} age Das Alter
 * @return {string} Die phrase
 */
function getAgePhrase(age) {
  return `Ich bin ${age} Jahre alt!`;
}

Hier kann ich definieren, dass die Funktion eine Zahl als Input erwartet und einen String zurückliefert. Auch kurze Zusammenfassungen kann ich dazu-schreiben. Es ist wieder wichtig zu erinnern, dass ich auch mit diesem Kommentar immer noch “nicht-kompatible” Daten in die Funktion schicken kann, aber mich die IDE versucht mit einer Warnung davon abzuhalten.

Typ-aliase definieren

Weiters lassen sich mit JSDoc auch Typ-aliase, also alternative Name für existierende Typen definieren. Hier ein Beispiel:

/**
 * Das Alter einer Person
 * @typedef {number} age
 */

/**
 * Generiert einen Satz der das Alter "sagt"
 * @param {age} age Das Alter
 * @return {string} Die phrase
 */
function getAgePhrase(age) {
  return `Ich bin ${age} Jahre alt!`;
}

Mithilfe dieses Aliases kann ich “bestimmten” Zahlen einen besser lesbaren Typ-namen geben. Es sind immernoch nur “normale” Zahlen, nur heißen sie anders. Typ-definitionen wie ich sie hier verwendet habe, können in jedem beliebigen js-File liegen und sind üblicherweise im gesamten Projekt zugänglich.

Eigene Objekt-typen definieren

Ein in meinen Augen besonders nützliches Feature sind eigene Objekt-typen wie beispielsweise dieser hier:

/** 
 * Ein Rechteck mit Länge und Breite
 * @typedef {Object} Rect
 * @property {number} width Die Länge
 * @property {number} height Die Breite
 */ 

Mit diesem Kommentar definiere ich eine “Art von Objekt” ähnlich wie eine Klasse, nur, dass es wirklich nur ein Objekt ist und nicht wie eine Klasse einen Konstruktor, Methoden und so weiter hat. Mit diesem Kommentar kann mich die IDE noch besser unterstützen.

/**
 * @type {Rect}
 */
let rect = { width: 10} // Warnung weil "height" fehlt.

Fazit

Obwohl natürlich JSDoc keine echte Typen-sicherheit gibt wie sie zum Beispiel in TypeScript oder anderen stark typisierten Sprachen vorhanden ist, ist es auf jeden Fall ein step-up, im Vergleich zu dem typenlosen wilden Westen in dem man sich normalerweise mit JavaScript aufhält. Ich würde es jedem Programmierer/Programmierin empfehlen sich einmal damit auseinanderzusetzen.

The comments are closed.