1 Punkte von GN⁺ 2025-12-16 | 1 Kommentare | Auf WhatsApp teilen
  • Ein Refactoring-PR im Svelte-Repository sorgte 2023 für Aufmerksamkeit unter TypeScript-Skeptikern, als auf JSDoc-basierten Code umgestellt wurde
  • Svelte erklärte, dies sei keine anti-TypeScript-Haltung, sondern Teil einer fortgesetzten Abhängigkeit von TypeScript
  • Der Text betont, dass JSDoc und TypeScript kein Gegensatz sind, sondern dass JSDoc selbst ein Teil von TypeScript ist
  • TypeScript fungiert als IntelliSense-Engine und übernimmt sowohl die Auswertung von JSDoc-Kommentaren als auch die automatische Codevervollständigung
  • JSDoc bietet ohne Build-Schritt dieselben statischen Analysefähigkeiten und erfüllt in modernen JS-Projekten praktisch die gleiche Rolle wie TypeScript

Der Svelte-PR und der Hintergrund der Debatte

  • Im Mai 2023 schaffte es ein internes Refactoring-PR aus dem Svelte-Repository auf die Startseite von Hacker News
    • In diesem PR wurden Typdeklarationen aus .ts-Dateien in JSDoc-Kommentare innerhalb von .js-Dateien verlagert
    • Manche interpretierten das als Ablehnung der Vorteile von TypeScript
  • Svelte-Gründer Rich Harris erklärte auf HN selbst: „Das ist nicht gegen TypeScript gerichtet“
    • Er erwähnte, dass Sveltes Bekenntnis zu TypeScript weiterhin sehr stark ist
  • Danach erschienen zahlreiche Beiträge zum Vergleich „TypeScript vs. JSDoc“, und die Sichtweise verbreitete sich, JSDoc sei „TypeScript ohne Build-Schritt

Ursprung und Wesen von TypeScript

  • Ende der 2000er bis Anfang der 2010er Jahre galt JavaScript als Sprache mit zu wenig Autovervollständigung und Typsicherheit
    • Microsoft-Entwickler begegneten dem, indem sie mit ScriptSharp C#-Code in JS umwandelten
  • Vor diesem Hintergrund entstand TypeScript und startete seinem Wesen nach als Build-Tool zur Verbesserung der JS-Entwicklung

TypeScript ist IntelliSense

  • TypeScript ist nicht nur eine Sprache, sondern fungiert als IntelliSense-Engine
    • Auch ohne .ts-Dateien werden Funktionen wie Codevervollständigung, Parameterinformationen und Symbolnavigation vom TypeScript-Sprachdienst bereitgestellt
    • In den meisten Editoren läuft beim Schreiben von JS-Code der TypeScript-Dienst im Backend

TypeScript ist JSDoc

  • Der TypeScript-Sprachdienst wird auch für die Auswertung von JSDoc-Kommentaren verwendet
    • Im CHANGELOG von TypeScript finden sich häufig Einträge zu neuen JSDoc-Funktionen
    • Auch JSDoc-basierte Projekte lassen sich mit tsconfig.json konfigurieren, und mit dem Befehl tsc ist eine Typprüfung möglich
  • Entwickler, die JSDoc verwenden, nutzen also bereits TypeScript

Erfahrungen mit JSDoc-basierten Projekten

  • Der Autor berichtet von der Erfahrung, das Frontend eines bestehenden Projekts auf Basis von JSDoc-Typkommentaren neu geschrieben zu haben
    • Abgesehen von Laufzeitfunktionen wie Enums (enum) lässt sich der Großteil der TypeScript-Ausdrucksmöglichkeiten auch mit JSDoc umsetzen
    • Generics haben eine etwas kompliziertere Syntax, fördern dafür aber eine aktivere Nutzung der Typinferenz
  • In JSDoc-Projekten kann man beim Klick auf eine Funktion direkt zum tatsächlichen Code springen, was die Developer Experience verbessert
  • Das TypeScript-Tooling-Ökosystem lässt sich auch in JSDoc-Projekten wiederverwenden
    • Zum Beispiel können Bibliotheken, die Typen aus OpenAPI- oder GraphQL-Schemata generieren, diese als JSDoc-Kommentare erzeugen

Fazit und weitere Beispiele

  • JSDoc ist keine Alternative zu TypeScript, sondern teilt sich dasselbe System statischer Analyse
    • Es ermöglicht gleichwertige Typsicherheit, während der Build-Schritt entfällt
  • Zusätzlich wird erwähnt, dass auch das webpack-Projekt auf JSDoc migriert wurde
  • Als TypeScript-Experte vertritt der Autor klar die Position: „JSDoc ist TypeScript

1 Kommentare

 
GN⁺ 2025-12-16
Hacker-News-Kommentare
  • Über mehrere Jahre hinweg habe ich beim Entwickeln und Warten von Web- und Robotiksoftware mit Python/JavaScript einiges gelernt.
    Typen existieren auch dann, wenn man sie nicht explizit angibt, und wenn man sie nicht angibt, existieren sie am Ende nur im Kopf.
    Aber der Kopf ist vergänglich und für andere schwer zugänglich.
    Deshalb ist Typisierung ein hervorragendes Mittel zur Dokumentation.
    JSDoc und TypeScript sind Standardformate, um Typen auszudrücken, und beide haben Vor- und Nachteile.
    Wichtig ist, Typen konsistent und vorhersehbar zu definieren.
    Ein Type Checker ist die Art, wie der Computer sagt: „Dann beweise es.“
    Nicht jedes Programm braucht dasselbe Maß an Beweisen, und übermäßiges Beweisen kann Verschwendung sein.
    Deshalb bevorzuge ich Sprachen, in denen ich nur so weit „beweisen“ muss, wie es nötig ist.

    • Der Aussage „Informationen, die nur im Kopf existieren, sind vergänglich“ stimme ich voll zu.
      Gerade bei der Arbeit habe ich schmerzhaft gelernt, dass zu den „anderen Menschen“ auch mein zukünftiges Ich gehört.
    • Rust gilt als Paradebeispiel für die „prove it“-Philosophie, aber ich denke, tatsächlich ist es nicht ganz so.
      Mit Rust kann man Einschränkungen über unsafe, Arc, clone und Ähnliches lockern, muss dann aber bewusst festlegen, welche Einschränkungen nicht bewiesen wurden.
      Bei Sprachen, in denen man „nicht beweisen muss“, ist dagegen schwer zu erkennen, welchen internen Ansatz sie gewählt haben.
      Rusts Ansatz erlaubt anfangs ein lockeres Arbeiten wie in Python, ist später aber bei Lesbarkeit und Skalierbarkeit deutlich im Vorteil.
    • Ich stimme zu, dass JSDoc und TypeScript denselben Zweck erfüllen.
      Es war nicht meine Absicht, ein bestimmtes Tool zu verteidigen, sondern nur zu betonen, dass beide Ausdrucksformen eines Typsystems sind.
    • Diese Lektion habe ich schon vor 25 Jahren an der Universität gelernt.
      Statisch typisierte Sprachen waren in Teamprojekten viel einfacher zu handhaben, und auch heute bevorzuge ich nach Möglichkeit statische Typen.
    • Ich stimme der Aussage „Typen existieren immer“ zu, aber Sprachen wie C#, in denen man Typen explizit angeben muss, erfordern viel mehr Arbeit als Ruby.
      Wenn man sich die nachträglich zu bestehenden JS-Bibliotheken hinzugefügten TypeScript-Typdefinitionen ansieht, ist die Komplexität enorm.
      Schon ein einzelner falscher Typ kann den gesamten Build zerstören.
      Am Ende muss man dynamische Sprachen auf eine Weise verwenden, bei der man selbst Verantwortung übernimmt.
  • Ich mag alles, was sich in JavaScript ohne Build-Schritt erstellen lässt.
    Modernes HTML/CSS, Web Components und JSDoc zusammen werden unterschätzt.
    Es ist nicht für alle geeignet, aber ich halte es für einen ausreichend modernen Kandidaten für einen Frontend-Stack.

    • Seit Node 24 lässt sich jetzt auch TypeScript ohne Build-Schritt ausführen.
    • Ich verstehe den Reiz eines Ansatzes ohne Build-Schritt, aber in der Praxis wird das Dependency-Management dadurch komplizierter.
      Dank Funktionen wie HMR sind die Kosten eines Build-Schritts auch stark gesunken.
    • Ich habe in den letzten 10 Jahren nie direkt JS-Code geschrieben, der tatsächlich so ausgeliefert wurde.
      Es geht immer durch Vite oder Webpack, daher spüre ich die Vorteile von buildlosem JS nicht wirklich.
    • Web Components zu bauen ist ziemlich schmerzhaft.
      Ich wünschte, es gäbe eine einfache Möglichkeit, komplexe Komponenten zu erstellen.
    • Der Vorteil der Kombination aus HTML+CSS+JSDoc ist die natürliche Integration mit den Browser-Entwicklertools.
      Das Nachverfolgen von Netzwerk-Requests, direktes Springen zum Quellcode, Setzen von Breakpoints und Ähnliches macht das Debugging viel intuitiver.
      Je größer das Projekt wird, desto wertvoller wird so eine Umgebung.
  • Als SPAs in Mode waren, war JSDoc der Retter beim Typmanagement.
    Danach kam der Google Closure Compiler und bot typbasierte Sicherheit auf JSDoc-Basis, und TypeScript unterstützte (TS)JSDoc zusammen mit eigener Syntax.
    Die Community entschied sich am Ende für TypeScript, und der Closure Compiler verschwand.
    Dadurch blieb (TS)JSDoc als Relikt aus der Zeit, als MS mit Google konkurrierte, zurück.
    Heute bietet TS viel mehr Funktionen wie Generics, Enums, Utility-Typen, Vitest-Typtests, Type Guards usw.
    Ich verwende TS und JSDoc zusammen — TS für den Code, JSDoc für die Dokumentation (@link, @see, @deprecated, @example usw.).

    • Tatsächlich verwendet modernes JSDoc den TypeScript-Sprachdienst.
      Generics, Utility-Typen, Type Guards, RegEx-Parsing und die meisten anderen TS-Funktionen lassen sich auch in JSDoc nutzen.
      Ich habe in einem privaten Projekt sogar alles einschließlich Generics komplett mit JSDoc umgesetzt.
    • Die obige Behauptung stimmt nicht.
      Dass (TS)JSDoc ein Relikt der Vergangenheit sei, ist Fehlinformation und sollte nicht ungeprüft weiterverbreitet werden.
    • Dieser Beitrag selbst ist gerade eine direkte Widerlegung dieser Behauptung.
  • Es heißt zwar, es gebe viele Typen, die sich mit JSDoc nicht ausdrücken lassen, aber ich hätte mir gewünscht, es wäre mit einem ganzheitlichen Sprachansatz wie bei Flow möglich gewesen.
    TypeScript hätte das auch tun können, aber ich weiß nicht, warum es das nicht getan hat.

    • Wenn es konkrete Beispiele gibt, würde ich sie gern hören.
      Ich habe früher auch so gedacht, aber beim Refactoring eines Projekts auf JSDoc habe ich meine Meinung geändert.
      In JSDoc kann man mit @template generische Slots definieren.
      Beispiel:
      /** @type {ReturnType<typeof useState<Book[]>>} */
      const [books, setBooks] = useState();
      
    • Inzwischen wurden fast alle Typsystemfunktionen auch der JSDoc-Syntax hinzugefügt.
    • Das TypeScript-Typsystem ist Turing-vollständig und hat daher praktisch unbegrenzte Ausdruckskraft.
      Relevanter Link
  • Mit JSDoc geschriebene Pakete bieten eine gute Developer Experience, weil man mit CMD/CTRL-Klick direkt zum echten Code springen kann.

    • Das lässt sich auch über Editor-Einstellungen anpassen.
    • Tatsächlich funktioniert das in TypeScript genauso.
  • Vor 5 Jahren sagte ein Sprecher auf einem Meetup: „Wenn du TypeScript nicht magst, ist JSDoc eine Alternative.“
    Ich erklärte, dass beides letztlich TypeScript sei, aber mein Chef glaubte mir nicht.

    • Ich denke, der Unterschied liegt nur im Grad der Syntaxkompression (syntax compression).
    • Die Aussage „JSDoc ist letztlich auch TypeScript“ ist nur halb richtig.
      JSDoc und TS drücken beide Typen explizit aus, aber die TS-Syntax ist deutlich mächtiger.
      Trotzdem ist JSDoc eine gute Wahl für Leute, die ihre JS-Umgebung beibehalten und zugleich von Typwerkzeugen profitieren wollen.
  • Als Gegenargument: JSDoc ist nicht TypeScript.
    Mit @typedef definierte Typen werden automatisch exportiert, und es gibt keine Möglichkeit, das zu steuern.
    Relevantes Issue
    Deshalb war es bei der Entwicklung von Bibliotheken lästig, dass IntelliSense unübersichtlich offengelegt wurde.

    • Für Web Components passt JSDoc ziemlich gut.
      Man kann die Datei „my-component.js“ einfach so kopieren, und sie funktioniert ohne Build.
      In großen Projekten bevorzuge ich aber die TS-Syntax.
    • Technisch ist der Einwand korrekt, aber mit einer passenden Steuerung von @import lässt sich das meiste lösen.
  • Ich stimme der Aussage zu, dass „JSDoc keine Alternative zu TypeScript ist“.
    JSDoc bietet ebenfalls statische Analyse, aber ohne Build-Schritt.
    Siehe Node-Dokumentation.

    • Intern gibt es aber weiterhin einen Build-Schritt.
      TS auf JSDoc-Basis funktioniert jedoch auch im Browser.
      Ich persönlich bevorzuge die Lesbarkeit der TS-Syntax, und mit Tools wie swc ist das Entfernen von Typen schnell genug.
    • Diese Funktion ist allerdings auf die Node-Umgebung beschränkt und funktioniert im Browser nicht.
  • Der Grund, warum sich TypeScript gegenüber anderen Alternativen durchgesetzt hat, ist, dass es keine neue Sprache wurde, sondern ein Type Checker blieb.
    Anfangs schwankte die Richtung etwas, aber das wurde passend korrigiert, und heute werden in den meisten Codebases nicht einmal Enums besonders häufig verwendet.

  • In VSCode kann man mit der Einstellung „TypeScript: Prefer Go To Source Definition“ direkt zur echten Quelle springen.
    Außerdem funktioniert es genauer, wenn man in tsconfig declarationMap: true hinzufügt.
    Ich bevorzuge fast immer, bei cmd+click den Quellcode zu sehen.