1 Punkte von GN⁺ 2025-05-20 | 1 Kommentare | Auf WhatsApp teilen
  • Release von Version 4 von Zod, einer Bibliothek für Schemadefinition und Validierung. Die stabile Version bringt große Performance-Verbesserungen und lange gewünschte Funktionen
  • Bei Geschwindigkeit und Bundle-Größe wurden deutliche Verbesserungen erzielt; die neue Mini-Version (v4-mini) reduziert die Bundle-Größe drastisch
  • Neu hinzugekommen sind eine Metadaten-Registry, die JSON-Schema-Konvertierung sowie die Inferenz rekursiver Typen
  • Die Entwicklererfahrung wurde durch Anpassung von Fehlermeldungen und ein mehrsprachiges Locale-System weiter verbessert
  • Mit der Einführung eines Core-Subpakets, das künftig beim Aufbau von Bibliotheken genutzt werden kann, steigt auch die Erweiterbarkeit deutlich

Einführung in Zod 4

Hinweise zum wichtigen Release

  • Nach einem Jahr intensiver Entwicklung ist Zod 4 als stabile Version erschienen
  • Die Entwicklung wurde durch das OSS Fellowship von Clerk unterstützt
  • Derzeit wird Zod 4 parallel zu Zod 3 ausgeliefert, was eine schrittweise Migration zu Zod 4 erleichtert
  • Detaillierte Hinweise zu einigen Breaking Changes finden sich im Migration guide

Hintergrund des Wachstums

  • Im Vergleich zu Zod 3 aus dem Jahr 2021 sind GitHub-Stars und wöchentliche Downloads von Zod 4 exponentiell gewachsen
  • Zod 4 ist deutlich schneller, schlanker und arbeitet effizienter mit dem TypeScript-Compiler
  • Neun lange geforderte Kernprobleme wurden gelöst

Benchmarks und Performance

  • Geschwindigkeitssteigerung:
    • String-Parsing: 14,71-mal schneller
    • Array-Parsing: 7,43-mal schneller
    • Objekt-Parsing (safeParse): 6,5-mal schneller
  • Es werden Skripte bereitgestellt, mit denen Benchmarks direkt im Repository ausgeführt werden können
  • Durch die verbesserte generische Struktur ist die Kompilierleistung beim Method Chaining mit .extend(), .omit() usw. um das 10-Fache gestiegen
  • In großen Schemas und Codebases verbessert sich die TypeScript-Kompiliergeschwindigkeit deutlich

Bundle-Größe und Zod Mini

  • Die grundlegende Bundle-Größe wurde um 57 % reduziert, wodurch v4 gegenüber v3 2,3-mal kleiner ist
  • zod/v4-mini bietet eine funktionsbasierte, tree-shakebare API und reduziert die Bundle-Größe um bis zu 85 %
  • Die Unterschiede zwischen den APIs von core und v4-mini sind in der offiziellen Dokumentation ausführlich beschrieben
  • Die Struktur wurde so gestaltet, dass Bundler ungenutzte Methoden leicht entfernen können

Metadaten-Registry und JSON-Schema-Unterstützung

  • Typed Metadata kann stark typisiert an Schemas registriert und verwaltet werden
  • Die globale Registry (z.globalRegistry) verarbeitet JSON-Schema-kompatible Metadaten und kann sie automatisch einbinden
  • Mit .meta() und .describe() lassen sich Schemas einfach dokumentieren
  • Mit .toJSONSchema() lassen sich Schemas in das JSON-Schema-Format umwandeln, inklusive automatischer Übernahme der Metadaten

Automatische Inferenz rekursiver Typen

  • Rekursive Objekttypen und gegenseitig rekursive Typen lassen sich natürlich definieren und inferieren, ohne separates Type Casting
  • Die Nutzbarkeit wurde gegenüber den bisherigen Mustern in Zod 3 deutlich verbessert
  • Auch bei rekursiven und gegenseitig rekursiven Typen können alle Schema-Methoden verwendet werden

Dateitypen und Validierungsfunktionen

  • Mit dem neuen file()-Typ können File-Instanzen validiert werden
  • Es gibt Validierung für verschiedene Datei-Beschränkungen wie Dateigröße (min, max) und MIME-Typen

Fehlermeldungen und Locale-System

  • Mit der globalen Locale-API (z.locales) ist mehrsprachige Unterstützung für Fehlermeldungen möglich
  • Die offizielle Funktion z.prettifyError bietet benutzerfreundliche Formatierung von Fehlern

Formatfunktionen und Template Literals

  • Bestehende String-Formate (email usw.) wurden in Funktionen auf höherer Ebene überführt, was Lesbarkeit und Tree Shaking verbessert
  • Es gibt verschiedene Optionen für E-Mail-RegEx, um unterschiedliche Validierungsanforderungen abzudecken
  • Unterstützung für Template-Literal-Typen: Im Typsystem darstellbare String-Muster und komplexe Kombinationen lassen sich leicht umsetzen

Neu hinzugefügte Zahlen- und bigint-Formate

  • Unterstützung für Ganzzahl- und Fließkommatypen mit fester Breite (int32, uint64 usw.)
  • Es können Schemas erzeugt werden, die automatisch Mindest-/Höchstgrenzen innerhalb sicherer Bereiche enthalten

Einführung von z.stringbool

  • String-basiertes Boolean-Parsing (yes, no usw.) ist möglich; Parsing im Stil von Umgebungsvariablen wird ebenfalls unterstützt
  • Truthy-/Falsy-Werte lassen sich anpassen

Vereinheitlichung der API zur Fehleranpassung

  • Mit dem vereinheitlichten Parameter error werden Struktur und Logik von Fehlermeldungen konsolidiert
  • Die bisherigen fehlerbezogenen APIs (message, invalid_type_error, errorMap) sind deprecated

Weitere wichtige Verbesserungen

  • Discriminated unions unterstützen verschiedenste Schemas, Verschachtelungen und Kombinationen
  • .literal() erlaubt jetzt mehrere Werte gleichzeitig
  • Benutzerdefinierte Validierung wie .refine() ist noch intuitiver integriert
  • Mit dem transform-bezogenen .overwrite() ist Nachbearbeitung möglich, ohne den Transformationstyp zu ändern

Erweiterbarkeit für Bibliotheken und neuer Core

  • Mit zod/v4/core wurden die Kernfunktionen in ein separates Subpaket ausgelagert, was Integration und Erweiterung über verschiedene Bibliotheken und Plattformen hinweg ermöglicht
  • Es gibt Leitfäden und Erweiterungsbeispiele für Bibliotheksentwickler

Abschluss

  • Zod 4 etabliert sich als Datenvalidierungsbibliothek mit großen Verbesserungen bei Typsicherheit, Performance, Erweiterbarkeit und Developer Experience
  • Weitere Design-Posts und Updates wurden bereits angekündigt
  • Es ist umfassende Unterstützung sowohl für bestehende Nutzer als auch für Bibliotheksentwickler vorbereitet

Viel Freude beim Parsen
— Colin McDonnell @colinhacks

1 Kommentare

 
GN⁺ 2025-05-20
Hacker-News-Kommentare
  • Der Autor selbst bittet um Rückmeldungen und liefert eine ausführliche Erklärung zur Versionsverwaltung. Er betont, dass npm nicht gut geeignet ist, eine Situation wie bei Zod zu handhaben, und weist darauf hin, dass unzählige Bibliotheken Zod-Interfaces/-Klassen direkt importieren und verwenden. Wenn Zod bei einem Major-Release geändert wird, müssten all diese Bibliotheken gleichzeitig nachziehen, was zu einer Versions-Explosion führen könnte. Stattdessen werde – ähnlich wie bei Go – für Breaking Changes ein neuer Subpath hinzugefügt. In TypeScript könne man mit nur zod@^3.25.0 gleichzeitig "zod/v3" und "zod/v4" unterstützen. Dadurch entstehe für Endnutzer ein schrittweiser Upgrade-Pfad.

    • Dank für die Beiträge zu Zod und Vorfreude insbesondere auf bessere tsc-Performance und Verbesserungen bei discriminated unions. Das Versionsmodell sei nachvollziehbar, aber für Nutzer wie ihn, die sich keine Sorgen über Konflikte bei transitiven Abhängigkeiten machen müssen, wäre ein einzelnes Paket als 4.0.0 vielleicht ebenfalls gut gewesen. Die nötige Umstellung der Imports auf "zod/v4" könne zusätzlichen Code-Lärm verursachen sowie weitere Umstände wie Konflikte mit automatischen IDE-Imports. Insgesamt wirke das Upgrade jedoch sehr vielversprechend, wofür er sich bedankt.

    • Entschuldigt sich, falls er es übersehen hat, weil er den Artikel auf dem Handy liest, und fragt, ob die größte Unannehmlichkeit im Zusammenhang mit .optional() in den diesmal gelösten 9/10 Top-Issues enthalten ist. Er erwähnt, dass Zod so gut sei, dass er es trotz der Unbequemlichkeiten weiter benutze, und bedankt sich für die großartige Bibliothek.

    • Dank dafür, dass mit der neuen Zod-Version viel manuell gehackter Code entfernt werden kann. Er nutzt selbst zod-key-parser, um Tippfehler zu reduzieren, und fragt sich, warum so eine Funktion nicht standardmäßig in der Bibliothek enthalten ist: ob sie als außerhalb des Scopes betrachtet wird oder einfach noch nicht implementiert wurde. Dazu teilt er relevante offene Diskussionen.

    • Betont, dass der Weg mit dem geringsten kurzfristigen Schmerz oft der beste ist, und verweist auf das Chaos rund um die Python-2/3-Migration.

    • Teilt die Erfahrung, erhebliche Schwierigkeiten gehabt zu haben, rekursive Typen und discriminated unions gleichzeitig zu verwenden, etwa wenn XML in JSON eingebettet ist, und hofft, dass sich die Lage mit diesem Update deutlich verbessert.

  • Jemand äußert Zweifel am Import zod/v4-mini und vermutet, dass dadurch die Bundle-Größe eher steigen könnte. Da die offizielle Dokumentation sagt, zod/v4 werde in den meisten Fällen empfohlen, würden App-Entwickler zod/v4 verwenden. Wenn Bibliotheksautoren zur Verringerung der Bundle-Größe zusätzlich zod/v4-mini einbinden, könnten am Ende beide Varianten im Bundle landen und Duplikate verursachen. Es wird gefragt, ob sich dieses Problem verringern ließe, wenn zod/v4 ein Wrapper um zod/v4-mini wäre.

  • Um die Migration auf Zod 4 zu erleichtern, wurden v3 und v4 gleichzeitig in zod@3.25 bereitgestellt. Kritisiert wird, dass diese Struktur wegen der Grenzen von npms Dependency-Management dazu geführt habe, dass v4 wie v3 aussehen müsse. Dabei wird auch auf Ineffizienzen im System der Peer Dependencies von npm hingewiesen.

    • Der Autor selbst erklärt erneut die an Golang angelehnte Versionsstrategie über zusätzliche Unterpfade. Wegen der Eigenheiten von npm sei das im Zod-Ökosystem schwer einzuführen, biete aber den Vorteil, v3 und v4 parallel zu unterstützen und eine schrittweise Migration zu ermöglichen.

    • Ein anderer meint, er stimme der früheren Aussage nicht unbedingt zu, dass wegen kaputter Peer Dependencies v4 als v3 getarnt worden sei. Vielmehr sei es ein Mittel für eine schrittweise Migration: Man ersetze nach und nach durch zod/v4 und upgrade dann vollständig auf v4.

    • Viele würden das kritisieren, dabei sei es weniger eine grundsätzliche Grenze von npm als vielmehr eine pragmatische Entscheidung, um eine Bibliothek mit großen Änderungen schrittweise umstellen zu können.

    • Jemand fragt, vielleicht aus einer durch langjährige npm-Nutzung geprägten Perspektive, welche bessere Methode es gäbe, als den Wechsel von v3 auf v4 nicht als großen Einmalsprung, sondern schrittweise zu unterstützen.

    • Obwohl er mit der Zod-4-Beta bereits große Verbesserungen erlebt habe, könne er in einer großen Codebasis wegen schwieriger Modulauflösungs-Settings nicht sauber upgraden. Er hätte sich daher eine Veröffentlichung einfach als neue Major-Version ohne Legacy-Schicht gewünscht. Zugleich teilt er die Erklärung des Autors zur Vermeidung einer „Versions-Explosion“, meint aber, dass die Schockwelle durch die parallele Unterstützung von v3 abgemildert werden könne.

  • Es wird gefragt, mit welchem Typmodell man Server-Antworten behandeln sollte, wenn die vom Server zurückgegebenen Typen je Endpoint unterschiedlich sind oder einzelne Felder – etwa bei anonymen Nutzern – null sein können. Wenn man dafür mehrere Funktionen wie normalizeUser oder normalizePost anlegt, werde die Pflege zunehmend komplex. Es wird nach Praxiserfahrungen gefragt, wie man dieses Problem löst.

    • Als Lösung wird ein Beispiel mit discriminated unions vorgeschlagen. Der gemeinsame Teil des Schemas werde als Objekt definiert und je nach konkreter Situation erweitert. Bei sehr vielen Fällen könne es natürlich trotzdem komplex werden, aber mit einem Schema-Validator lasse sich das wenigstens strukturiert halten.

    • Ideal wäre es, die Typstruktur von User als Single Source of Truth festzulegen, etwa in Form einer discriminated union. Unter der Annahme eines Python-Backends wird eine Struktur aus mehreren Pydantic-Modellen plus Union sowie TypeScript-Client-Typen vorgeschlagen, die per OpenAPI-/GraphQL-Code-Generierung erzeugt werden.

    • Mit einem konkreten Praxisbeispiel ließe sich besser antworten, aber wenn man einem Union-Typ eine unterscheidende Property wie z. B. "user_type" hinzufügt, werde der Zugriff auf einzelne Felder leichter, weil das Typsystem je nach Situation die passenden Eigenschaften erkennen könne.

    • Es wird eindringlich empfohlen, dass der Server die Typen direkt exportieren sollte. Separate Typen auf Client-Seite immer wieder neu zu schreiben, sei ineffizient. Für ein Python-Backend wird erklärt, wie mit Pydantic automatisch eine OpenAPI-Spezifikation erzeugt und daraus Typen für den TypeScript-Client generiert werden können.

    • Es wird angemerkt, dass GraphQL für solche Fälle passend entworfen wurde. Mit TypeScript-GraphQL-Bibliotheken könne man die Form von Query-Ergebnissen automatisch ableiten, und je nach ausgewählten Feldern würden passende Response-Typen dynamisch erzeugt.

  • Es wird erwähnt, dass ArkType trotz der Verbesserungen in Zod 4 weiterhin deutlich schneller sei. Bestehende Bibliotheken hätten wegen Rückwärtskompatibilität und beibehaltener Syntax Grenzen bei der Performance. Laut Analyse des eigenen Projekts fiel die Wahl auf ArkType wegen Performance und TypeScript-Ergonomie.

    • Jemand hat die Geschwindigkeitsmetriken von ArkType gesehen und fragt sich, welche praktische Auswirkung diese Geschwindigkeit eigentlich hat. In üblichen Situationen wie Formularvalidierung scheine der Einfluss gering zu sein. Er fragt, ob es eher in performancekritischen Bereichen wie ultraschneller API-Inputvalidierung eingesetzt werde.

    • ArkType war zwar nicht Teil seiner Recherche, aber er hatte danach gesucht, weil ihm die TypeScript-Ergonomie wichtig war. Trotzdem plane er keinen Wechsel weg von Zod.

    • Jemand berichtet, dass die Erfahrung mit ArkType sehr schwierig gewesen sei, und er Zod wegen der besseren Benutzbarkeit bevorzuge.

    • Es wird gefragt, warum man sich speziell für ArkType statt TypeBox entschieden habe.

  • Glückwünsche an das Zod-Team zum neuen Release. Angesichts der vielen Breaking Changes in der Migrationsanleitung bestehe die Sorge, dass große, stark von Zod abhängige Projekte stark belastet und schwer zu verwalten seien. Aus der Erfahrung mit der Pflege alter Frontend-Projekte heraus wird Bedauern über den aktuellen JS-Entwicklungstrend geäußert, bei dem viele Bibliotheken große Änderungen und oft unzureichende Dokumentation mit sich brächten.

    • Jemand betreibt mehrere große Next.js-Apps und berichtet, dass das vergangene Jahr mit Next.js 14→15, Next.js pages→app router, React 18→19, Eslint 8→9 und Tailwind 3→4 voller großer und schwieriger Veränderungen gewesen sei. Es sei wirklich hart gewesen, und er habe sich sogar gedacht, er hätte lieber mit Django gebaut. Besonders die Migration von Tailwind 3 auf 4 sei rückblickend überraschend die schmerzhafteste gewesen.

    • Es wird erklärt, dass zur Abmilderung solcher Probleme die Strategie eingeführt wurde, zusätzlich eine mini-Edition bereitzustellen. Das erleichtere schrittweise Umstellungen, und im Hinblick auf optimale Tree-Shaking-Eigenschaften sei die Einführung von mini unvermeidlich gewesen, um gegenüber Alternativen konkurrenzfähig zu bleiben.

    • Es wird vorgeschlagen, dass sich solche Migrationen mit Tools wie LLMs ohne große Schwierigkeiten bewältigen lassen.

  • Es wird gesagt, dass Zod den bisherigen Alternativen klar überlegen sei. Gleichzeitig sei es in der Webentwicklung Realität, dieselbe Datenstruktur auf mehrere Arten beschreiben zu müssen: zur JS-Inputvalidierung, für API-Spezifikationen via Swagger sowie getrennt auf Server und Client. Das sei zu repetitiv und mühsam.

    • Bedauert wird, dass TypeScript so strikt ein Werkzeug nur für statische Prüfungen bleiben will. Es müsse nicht unbedingt Runtime-Checks übernehmen, aber es wäre wünschenswert, Typdaten von Klassen/Funktionen/Objekten leichter nach außen nutzen zu können. Derzeit müssten verschiedene Tools jeweils ihre eigenen Modelle und Builder definieren, was Duplikation unvermeidlich mache. Als Standardisierungsversuch wird das Projekt Standard Schema genannt, das sich offenbar mit wichtigen Validierungsbibliotheken integrieren werde, während Erweiterungen für API-Spezifikationen und ORMs noch in einem frühen Stadium seien.

    • Der Kern solcher Tools sei, einmal etwas zu definieren und die Type-Safety über die gesamte App zu verbreiten. Ein Zod-Schema könne dabei eine Art Single Source of Truth sein.

    • Ergänzend wird angemerkt, dass viele Menschen diese umständliche Struktur zwar lästig finden, aber zugleich ablehnend reagieren, wenn vorgeschlagen wird, alles mit TypeScript allein – einschließlich Zod – zu vereinheitlichen.

    • Alle APIs und Systeme seien in ständigem Wandel und Experimentieren begriffen. Die Realität mit immer mehr komplexen Schichten sei zwar ein Nachteil, aber in Situationen, in denen „das Projekt einfach nur funktionieren muss“, bedeute sie am Ende vor allem mehr Arbeit.

    • Insgesamt könne man auch End-to-End-Type-Safety wie bei trpc einsetzen, doch dafür müssten Frontend und Backend beide in TypeScript vereinheitlicht sein, und andere Plattformen außerhalb des Webs, etwa Mobile, seien dann in der Praxis schwerer einzubinden.

  • Jemand sagt, kein Experte zu sein, hält aber das schema-basierte JSON-Schema für eine gute Wahl, weil sich Validatoren dafür auch in anderen Sprachen als TypeScript implementieren lassen. Unter Verweis auf Bibliotheken wie ajv.js.org fragt er nach einem Vergleich mit Zod.

    • Zod könne nicht nur JSON-Formen validieren, sondern vollständige JS-Objekte wie Datumswerte oder Klasseninstanzen, also Daten, die sich nicht als JSON ausdrücken lassen. Es könne auch beim JSON-Umwandlungsprozess eingesetzt werden, indem man das Schema stringbasiert beschreibt und dann etwa einen ISO-Datumsstring validiert und in ein Date-Objekt umwandelt.

    • Zod 4 unterstützt die Umwandlung von Zod-Schemata in JSON-Schema, wofür früher eine externe Bibliothek nötig war. Ein großer Unterschied von Zod seien die Funktionen preprocess und refine, mit denen sich vor der Validierung Callbacks einfügen lassen. So könne man z. B. MM/DD/YYYY vor der Prüfung in DD/MM/YYYY umwandeln – etwas, das mit JSON-Schema nicht möglich sei.

    • JSON-Schema sei ebenfalls eine gute Wahl; in diesem Fall eigne sich TypeBox gut zur Erzeugung. Man könne avj verwenden oder ein eigenes Validierungssystem. Eine eigene Validierung sei schneller, aber nur synchron, während avj auch asynchrone Validierung ermögliche und deshalb bei tiefergehender Prüfung von Vorteil sei.

    • Wenn es um die Nutzung in mehreren Sprachen geht, sei JSON-Schema am universellsten. Wenn man es in OpenAPI einbettet, könne man zusätzlich automatisch API-Dokumentation erzeugen.

  • Jemand hat gerade erst begonnen, Zod in einem neuen Projekt einzuführen, und freut sich, dass der Zeitpunkt dieses Releases perfekt passt. Wäre alles nach Plan gelaufen, hätte er für die Migration auf v4 viele Änderungen gebraucht, aber das Timing sei ideal.

  • Jemand reagiert überrascht auf die unerwartet vielen negativen Kommentare. Beim Testen früher v4-Versionen habe ihm die neue API zwar gefallen, aber der Migrationspfad habe ihm Sorgen bereitet. Er habe sogar überlegt, eine Veröffentlichung unter einem separaten Paketnamen vorzuschlagen, bewertet die vom Autor gewählte Methode aber im Ergebnis als äußerst gelungen. Dadurch könne man v4 sofort übernehmen, ohne auf Dependency-Updates warten zu müssen.

    • Er selbst glaube auch, dass man in Bereichen wie der Validierung nicht die Kapazität habe, alles auf einmal zu migrieren. Die aktuelle Methode sei praktisch gesehen wohl optimal.