Release von Zod 4
(zod.dev)- Zod 4 wurde nach einem Jahr Entwicklung als stabile Version veröffentlicht, behebt Designgrenzen von Zod 3 und verbessert Performance, Bundle-Größe und TypeScript-Kompilierungseffizienz deutlich
- Zod 3, das im Mai 2021 erschien, wuchs von 2.700 GitHub-Stars und 600.000 wöchentlichen Downloads auf heute 37,8k Stars und 31 Millionen wöchentliche Downloads
- In Benchmarks wurde das Parsen von Strings 14-mal, von Arrays 7-mal und von Objekten 6,5-mal schneller; auch die
tsc-Typinstanziierungen sanken in einem einfachen Beispiel von über 25.000 auf etwa 175 - Die Kern-Bundle-Größe schrumpfte gzip-komprimiert von
12.47kbbei Zod 3 auf5.36kbbei der normalen Version von Zod 4; Zod Mini, eine tree-shakebare funktionale API, kommt auf nur1.88kb - Zu den neuen Funktionen gehören JSON-Schema-Konvertierung, Metadaten-Registries, rekursive Objekttyp-Inferenz, Internationalisierung, Pretty-Printing von Fehlern, Template-Literal-Typen,
z.stringbool(), ein vereinheitlichtererror-Parameter und ein verbessertesz.discriminatedUnion()
Warum Zod 4 eine neue Major-Version ist
- Zod 4 ist nach einem Jahr aktiver Entwicklung als stabile Version erschienen und implementiert lange gewünschte Funktionen auf einer schnelleren, kleineren und
tsc-effizienteren Grundlage - Zod v3.0 wurde im Mai 2021 veröffentlicht; damals hatte es 2.700 GitHub-Stars und 600.000 wöchentliche Downloads
- Heute verzeichnet Zod 37,8k GitHub-Stars und 31 Millionen wöchentliche Downloads
- Vor 6 Wochen, als die Beta erschien, lagen die wöchentlichen Downloads bei 23 Millionen
- Nach 24 Minor-Versionen hatte die Zod-3-Codebasis ihre Grenzen erreicht, und für die am häufigsten gewünschten Funktionen und Verbesserungen waren Breaking Changes nötig
- Zod 4 schließt 9 der 10 öffentlich am häufigsten per Upvote gewünschten Issues
Parsing-Performance und TypeScript-Kompilierungseffizienz
- Zod 4 bietet Benchmarks, die direkt im Repository ausgeführt werden können
- Verbesserungen bei der Parsing-Performance:
- String-Parsen: 14-mal schneller
- Array-Parsen: 7-mal schneller
- Objekt-Parsen: 6,5-mal schneller
- Der Benchmark für Objekt-Parsen verwendet den Moltar validation library benchmark
- Gemessen mit
tsc --extendedDiagnosticssinkt bei der Kompilierung einer einfachen Datei die Zahl der Typinstanziierungen drastisch- mit
"zod/v3": über 25.000 - mit
"zod/v4": etwa 175
- mit
- Zod 4 vermeidet eine Explosion von Instanziierungen, indem die Generics von
ZodObjectund anderen Schema-Klassen neu entworfen und vereinfacht wurden - Das wiederholte Verketten von
.extend()und.omit()benötigte in Zod 34000mszum Kompilieren; ein zusätzlicher Aufruf von.extend()konnte den Fehler"Possibly infinite"auslösen - Dasselbe Muster kompiliert in Zod 4 in
400msund ist damit 10-mal schneller - Künftig könnte zusammen mit dem Compiler
tsgodie Editor-Performance von Zod 4 auch auf größere Schemas und Codebasen skaliert werden
Bundle-Größe und Zod Mini
- Die Kern-Bundle-Größe wurde durch Bundling eines einfachen
z.boolean()-Validierungsskripts mitrollupverglichen - Kern-Bundle-Größe, gzip-komprimiert:
- Zod 3:
12.47kb - Zod 4 normale Version:
5.36kb
- Zod 3:
- Das Kern-Bundle der normalen Zod-4-Version ist etwa 57 % kleiner als Zod 3 und wurde auf das 2,3-Fache reduziert
- Die methodenzentrierte API von Zod ist grundsätzlich schwer zu tree-shaken; selbst ein einfaches
z.boolean()-Skript zieht Implementierungen ungenutzter Methoden wie.optional()und.array()mit hinein - Zod Mini bietet eine funktionale, tree-shakebare API, die
zod1:1 entspricht- Wo Zod Methoden verwendet, nutzt Zod Mini typischerweise Wrapper-Funktionen
- Parsing-Methoden sind in Zod und Zod Mini identisch
- Über die universelle Methode
.check()lassen sich Verfeinerungen (Refinements) hinzufügen
- Normales Zod bleibt für die meisten Anwendungsfälle die empfohlene Wahl; Projekte mit ungewöhnlich strengen Bundle-Größenbeschränkungen können Zod Mini in Betracht ziehen
- Bei Verwendung von
zod/minibeträgt die gzip-Bundle-Größe1.88kb- Gegenüber Zod 3 entspricht das einer Reduktion um 85 % bzw. dem Faktor 6,6
- Vergleichstabelle: Zod 3
12.47kb, Zod 4 normal5.36kb, Zod 4 Mini1.88kb
- Mehr dazu in der Dokumentation zu
zod/mini
Metadaten und JSON Schema
- Zod 4 führt ein neues System ein, um stark typisierte Metadaten zu Schemas hinzuzufügen
- Die Metadaten werden nicht im Schema selbst gespeichert, sondern in einer Schema-Registry, die Schema und typisierte Metadaten verknüpft
- Mit
z.registry()lässt sich eine Registry erstellen; über die Methode.register()eines Schemas ist auch eine bequeme Registrierung möglich - Zod exportiert die globale Registry
z.globalRegistry, die gemeinsame JSON-Schema-kompatible Metadaten entgegennimmt - Die Methode
.meta()fügt ein Schema bequem zuz.globalRegistryhinzu - Aus Kompatibilitätsgründen zu Zod 3 bleibt
.describe()erhalten, in Zod 4 wird jedoch.meta()empfohlen - Zod 4 bietet eine First-Party-JSON-Schema-Konvertierung über
z.toJSONSchema() - Die Metadaten aus
z.globalRegistrywerden automatisch in die JSON-Schema-Ausgabe übernommen - Informationen zur Anpassung des erzeugten JSON Schema finden sich in den JSON Schema docs
Neue Schema-Ausdrücke und Typfunktionen
- Zod 4 kann rekursive Objekttypen korrekt inferieren
- Rekursive Typen und gegenseitig rekursive Typen lassen sich darstellen
- Anders als beim Muster für rekursive Typen in Zod 3 ist kein Type Casting nötig
- Das resultierende Schema ist eine normale
ZodObject-Instanz, und der volle Methodenumfang bleibt nutzbar
- Es wurde ein File schema zur Validierung von
File-Instanzen hinzugefügt z.templateLiteral()bildet Template-Literal-Typen aus TypeScript ab- Zod-Schematypen, die sich zu Strings umwandeln lassen, speichern intern reguläre Ausdrücke
- Dazu zählen Strings, String-Formate wie
z.email(), Zahlen, Boolean, BigInt, Enum, Literal, Undefined/Optional, Null/Nullable und andere Template Literals - Der Konstruktor von
z.templateLiteralverbindet diese zu einem einzigen Super-Regex - String-Formate wie
z.email()werden korrekt erzwungen, benutzerdefinierte Refinements jedoch nicht - Mehr dazu in den template literal docs
- Neue Zahlenformate für Integer fester Breite und Fließkommatypen wurden hinzugefügt
- Sie geben
ZodNumber-Instanzen zurück, bei denen passende inklusive Minimum-/Maximum-Beschränkungen bereits gesetzt sind
- Sie geben
- Es wurden auch BigInt-Zahlenformate hinzugefügt, die Bereiche oberhalb dessen abdecken, was sich mit JavaScript-
numbersicher darstellen lässt- Sie geben
ZodBigInt-Instanzen zurück, bei denen passende inklusive Minimum-/Maximum-Beschränkungen bereits gesetzt sind
- Sie geben
z.literal()kann jetzt optional mehrere Werte annehmen
Fehler, Internationalisierung und String-Formate
- Zod 4 führt eine neue
locales-API zur globalen Übersetzung von Fehlermeldungen in mehrere Sprachen ein - Eine vollständige Liste der unterstützten Locales steht unter Customizing errors und wird bei neuen unterstützten Sprachen aktualisiert
- Zod implementiert die Top-Level-Funktion
z.prettifyError, umZodErrorin einen benutzerfreundlich formatierten String umzuwandeln- Das aktuelle Format ist nicht konfigurierbar
- Es kann sich künftig ändern
- Wer bereits
zod-validation-errornutzt, kann dies weiterhin tun
- Alle String-Formate wie etwa Email wurden zu Top-Level-Funktionen des
z-Moduls hochgestuft- Das ist kompakter und besser für Tree Shaking
- Entsprechende methodenbasierte APIs wie
z.string().email()können weiter genutzt werden, sind aber deprecated - Sie sollen in der nächsten Major-Version entfernt werden
- Die API
z.email()unterstützt benutzerdefinierte reguläre Ausdrücke- Es gibt kein einziges kanonisches Regex für Email-Adressen; je nach Anwendung können strengere oder lockerere Regeln sinnvoll sein
- Zod exportiert der Bequemlichkeit halber einige gebräuchliche Regexe
Boolean-Konvertierung und vereinfachte Fehleranpassung
- Das bisherige
z.coerce.boolean()ist eine einfache API, die falsy-Werte infalseund truthy-Werte intrueumwandeltfalse,undefined,null,0,"",NaNusw. werden zufalse- Dieses Verhalten ist konsistent mit anderen
z.coerce-APIs
- Für eine differenziertere Boolean-Coercion im Stil von Umgebungsvariablen führt Zod 4
z.stringbool()ein- Truthy- und falsy-Werte lassen sich anpassen
- Mehr dazu in den
z.stringbool()docs
- Die meisten Breaking Changes in Zod 4 betreffen die API zur Fehleranpassung
- Die Fehleranpassung wurde auf einen einzigen Parameter
errorvereinheitlichtmessagewird durcherrorersetzt- Der Parameter
messagewird weiterhin unterstützt, ist aber deprecated invalid_type_errorundrequired_errorwerden durcherrorin Funktionssyntax ersetzt- Auch
errorMapwird durcherrorin Funktionssyntax ersetzt
Komponierbarkeit, Refinements und Transformationen
z.discriminatedUnion()unterstützt jetzt mehrere Schematypen, die zuvor nicht unterstützt wurden- darunter Union und Pipe
- Eine discriminated union kann als Mitglied einer anderen discriminated union verwendet werden und ist damit komponierbar
- In Zod 3 wurden Refinements in der Klasse
ZodEffectsgespeichert, die das ursprüngliche Schema umschloss- Diese Struktur machte es unpraktisch,
.refine()mit anderen Schema-Methoden wie.min()zu kombinieren
- Diese Struktur machte es unpraktisch,
- In Zod 4 werden Refinements intern im Schema gespeichert, sodass sich
.refine()natürlich mit anderen Schema-Methoden kombinieren lässt - Die neue Methode
.overwrite()beschreibt Transformationen, die den inferierten Typ nicht verändern.transform()erzeugt einen Ausgabetyp, der zur Laufzeit nicht introspektierbar ist, und die Transformationsfunktion ist eine Blackbox, die beliebige Werte zurückgeben kann- Deshalb gibt es keine sichere Möglichkeit, sie in JSON Schema zu konvertieren
.overwrite()gibt eine Instanz der ursprünglichen Klasse zurück- Die Overwrite-Funktion wird als Refinement gespeichert und verändert den inferierten Typ nicht
- Die bestehenden Methoden
.trim(),.toLowerCase()und.toUpperCase()wurden mithilfe von.overwrite()neu implementiert
Eine Grundlage für Library-Autoren
- Mit der Einführung von Zod Mini wurde das Subpackage
zod/v4/coregeschaffen, das die Kernfunktionalität enthält, die sich Zod und Zod Mini teilen zod/v4/coreerweitert Zod von einer einfachen Library zu einer schnellen Validierungsgrundlage, die in andere Libraries eingebettet werden kann- Wer eine Schema-Library bauen möchte, kann sich an den Implementierungen von Zod und Zod Mini orientieren und auf
zod/v4/coreaufbauen - Für Library-Autoren gibt es den Leitfaden For library authors
- Er behandelt Best Practices für das Aufbauen auf Zod
- Er beantwortet häufige Fragen dazu, wie sich Zod 3, Zod 4 und Mini gleichzeitig unterstützen lassen
1 Kommentare
Meinungen auf Hacker News
Ich bin der Autor, fragt mich alles. Zur Versionspolitik habe ich die Gründe für diesen Ansatz recht ausführlich zusammengefasst: https://github.com/colinhacks/zod/issues/4371
Letztlich ist npm nicht dafür ausgelegt, die Situation, in der Zod steckt, gut zu handhaben. Dutzende bis Hunderte Libraries importieren direkt Interfaces/Klassen von Zod und verwenden sie in ihrer öffentlichen API; jedes Mal, wenn Zod eine neue Major-Version veröffentlicht, müssten diese Libraries ebenfalls eine neue Major-Version herausbringen
Für sich genommen ist das plausibel, aber bei Zod könnte dadurch für alle eine schmerzhafte Versionslawine entstehen, und es sah so aus, als würde ein beträchtlicher Teil des Ökosystems für immer auf v3 festhängen
Deshalb haben wir, ähnlich wie bei Go, den Weg gewählt, statt einer neuen Version mit Breaking Changes einen neuen Unterpfad zum Paket hinzuzufügen. Im TypeScript-Ökosystem kann eine Library nur
zod@^3.25.0als Peer Dependency haben und aus"zod/v3"sowie"zod/v4"das Benötigte importieren, um beide Versionen gleichzeitig zu unterstützenIch verstehe zwar, warum wegen besonderer Umstände eine etwas ungewöhnliche Versionspolitik gewählt wurde, aber aus Sicht eines Teams, das sich keine Sorgen über Zod-Versionskonflikte in transitiven Abhängigkeiten machen muss, wäre ein Paket
4.0.0ebenfalls wünschenswertWenn ich es richtig verstanden habe, muss man Imports auf
"zod/v4"ändern; das ist eine sehr laute Änderung, und es kann lästig werden, per Lint-Regel abzufangen, dass die IDE automatisch aus'zod'importiert.optional()in TypeScript zu den gelösten Top-9-/Top-10-Issues gehört: https://github.com/colinhacks/zod/issues/635Das war der größte Schmerzpunkt bei Zod, aber Zod ist trotzdem so gut, dass ich es weiter in Kauf nehme
Ich frage mich, ob das als außerhalb des Scopes von Zod betrachtet wird oder ob einfach noch keine Zeit für die Implementierung war. Die zugehörige Diskussion ist unter https://github.com/colinhacks/zod/discussions/2134 zu finden
3.25.0ist, klingt das für mich ziemlich unsinnigIch habe seit Monaten die Alpha-Version von Zod verwendet und wollte einfach meine
package.jsonanpassen, um zu upgraden; jetzt werde ich wohl die gesamte Git-Historie durchforsten müssenIch bin dem Projekt sehr dankbar, aber genau dieses Feedback muss ich geben: Das wirkt unnötig schwer gemacht. Ich frage mich, ob man nicht neben
3.xauch 4.x hätte veröffentlichen könnenDie Aussage, dass „Zod 4 zur Vereinfachung der Migration als Teil des Releases
zod@3.25zusammen mit Zod 3 ausgeliefert wird und über den Unterpfad"/v4"importiert werden soll“, wirkt wie ein Zeichen dafür, dass npm Dependency Management völlig chaotisch istPeer Dependencies sind so kaputt, dass v4 so tun muss, als wäre es v3
Es stimmt, dass npm die Situation, in der Zod steckt, nicht gut bewältigt. Allerdings steht Zod unter der Einschränkung, nahezu keine Libraries einzubinden. Dutzende bis Hunderte Libraries importieren Interfaces/Klassen direkt aus
"zod"und verwenden sie in ihrer öffentlichen APISolche Libraries müssten jedes Mal, wenn Zod die Major-Version erhöht, ebenfalls eine neue Major-Version veröffentlichen, und bei Zod könnte das eine Versionslawine auslösen, die für alle schmerzhaft wäre. Ehrlich gesagt sah es so aus, als würde ein beträchtlicher Teil des Ökosystems für immer auf v3 festhängen
Deshalb haben wir, ähnlich wie bei Go, statt für jedes Release mit Breaking Changes eine neue Paketversion herauszugeben, einen neuen Unterpfad hinzugefügt. Im TypeScript-Ökosystem kann man mit einer einzigen Peer Dependency
zod@^3.25.0gleichzeitig"zod/v3"und"zod/v4"unterstützenAlso die Verwendungen nach und nach zu
import ... from 'zod/v4'refaktorisieren und danach vollständig auf v4 hochgehenIm Gegenteil: npm bietet sogar mehr Auswege, weil man bei Bedarf mehrere Versionen parallel ausführen oder Teile des transitiven Dependency-Graphen gezielt überschreiben kann
Welches Paketverwaltungssystem löst dieses Problem? Selbst „stabile“ Plattformen wie Maven behandeln solche Probleme, indem sie Versionen unter neuen Namespaces veröffentlichen, wie damals Apache Commons beim Wechsel von v2 auf v3
Eine Frage, die mich schon lange beschäftigt: Ich habe gehört, dass Zod dafür passen könnte, aber selbst nach einem Blick in die Dokumentation ist mir nicht ganz klar, wie man das macht.
Angenommen, eine Server-API gibt präzisere Typen zurück, als sie ausdrücken kann. Zum Beispiel gibt
api/:postid/authoreinen User zurück, aber das kann ein normaler User oder ein anonymer User sein, sodass Felder wieusernameundlocationals null kommen können. In diesem Fall möchte man das User-Objekt vielleicht als discriminated union darstellen.Auch Objekte von anderen Endpunkten müssen eventuell typtransformiert werden. Ein User enthält manchmal
Post[], und wenn ein Post ein Moderator-Beitrag ist, kann er spezielle Eigenschaften haben.Früher habe ich Funktionen wie
normalizeUser()undnormalizePost()geschrieben, aber das wurde schnell unübersichtlich. Weil jeder Endpunkt andere Teilmengen des User/Post-Modells zurückgab, hatte ich am Ende etwa fünf Varianten vonnormalizePost, und das war viel zu chaotisch. Ich frage mich, wie man solche Probleme normalerweise löst.Also etwa
success- undfailed-Objekte anhand eines diskriminierenden Felds wiestatustrennen. Wenn es viele spezielle Moderator-Eigenschaften gibt, man sie aber nicht alle aufzählen oder prüfen möchte, kann man ein Passthrough-Verhalten definieren.Auch wenn mehrere Methoden unterschiedliche Schemas haben: Wenn es gemeinsame Teile gibt, kann man ein gemeinsames Objekt-Schema erstellen und darauf Objekte mit zusätzlichen Feldern aufbauen. Bei vielen Möglichkeiten bleibt es trotzdem unordentlich, aber wenn die Situation ohnehin unordentlich ist, kann ein Validator diese Unordnung zumindest validieren.
Wenn es kein Full-Stack-TypeScript ist, kann man zum Beispiel in einem Python-Backend die verschiedenen
User-Formen als Pydantic-Modelle und Unions definieren und dann über OpenAPI-/GraphQL-Schema-Generierung und Codegenerierung TypeScript-Client-Typen erzeugen."user_type"hinzufügt, lassen sich Normal- und Sonderfälle leichter behandeln.Wenn man zum Beispiel
user.user_type === 'authenticated'prüft, weiß das Typsystem danach, dassuser.nameverwendet werden kann.TypeScript-Bibliotheken für GraphQL-Queries können die Antwortform dynamisch aus der Form der ausgewählten Felder ableiten. Wenn man
{ user { username posts { text } } }auswählt, hat der Antworttypposts; wenn man nur{ user { username } }auswählt, fehlt die Eigenschaftpostsvollständig.Der Server weiß, welche Daten er sendet, also sollte er diese Information dem Client als Metadaten bereitstellen. Praktisch kann das etwa so aussehen: Ein Python-Backend verwendet Pydantic-Schemas, daraus wird automatisch eine OpenAPI-Spezifikation erzeugt, und der Client generiert daraus Typen.
Zod ist deutlich besser als die Alternativen, die ich gesehen habe, aber manchmal fühlt sich schon die Tatsache, dass diese explizite Validierung nötig ist, wie ein Scheitern dessen an, wo die moderne Webentwicklung gelandet ist.
In der Full-Stack-Entwicklung ist es extrem frustrierend, dieselbe Form auf mehrere Arten beschreiben zu müssen. Man braucht JS-Eingabevalidierung, Swagger für API-Definitionen, serverseitige Eingabevalidierung, ein ORM für Schema-Konformität und dann noch separate TypeScript-Definitionen für Server und Client; das wird ermüdend.
TypeScript fühlt sich wie die beste Single Source of Truth an, die wir haben, aber in der Praxis definieren Tools, die Reflection versuchen, jeweils ihr eigenes Modell und ihre eigenen Builder neu. Allein große Bereiche, in denen Reflection zentral ist, gibt es fünf, und für jeden mehrere Implementierungen.
Das alte TypeScript-Type-Emission-Tool
reflect-metadatastellt einige Runtime-Typinformationen bereit, zielt aber auf sehr alte Decorator- und Metadata-Spezifikationen ab: https://www.npmjs.com/package/reflect-metadataVielleicht stehen wir ja am Anfang einer Vereinheitlichung. Das Projekt Standard Schema scheint von den meisten großen Validierungsbibliotheken unterstützt zu werden. Das auf API-Definitionen oder ORM-Tools auszuweiten, ist allerdings noch sehr früh.
https://github.com/standard-schema/standard-schema?tab=readm...
Ändert man etwas einmal im Zod-Schema, wird es zusammen mit der Typprüfung durch die ganze App propagiert. Das Zod-Schema wird damit zur Single Source of Truth.
Wenn bereits ein JSON-Schema-/Swagger-Schema existiert, kann man daraus Zod generieren. Wenn man ein TypeScript-ORM verwendet, gibt es mit ziemlicher Sicherheit einen Zod-Generator.
Ehrlich gesagt ist Zod so weit verbreitet, dass es für mich zur vereinheitlichten Schema-Definition geworden ist, auf die andere Teile des Stacks aufbauen können. Weil man die Typen direkt definiert, halten Entwickler sie tatsächlich aktuell. Die Swagger-Dokumentation in Unternehmen hinkt Änderungen immer hinterher.
Der Status quo ist nur dann in Ordnung, wenn man mit Kunden und Arbeitgebern zu tun hat, die einfach nur Ergebnisse wollen und sich nicht für die Vorgehensweise interessieren. In diesem Kontext erhöhen diese unglücklichen Komplexitätsschichten immerhin die abrechenbaren Stunden.
Natürlich unter der Voraussetzung, dass Zod die von ihnen gewählte TypeScript-Bibliothek für Schema-Definition und Validierung ist.
Zod 4 sieht gut aus, aber selbst mit den neuesten Verbesserungen ist ArkType immer noch um einen einstelligen Faktor schneller.
Für Abwärtskompatibilität und Syntaxkompatibilität ist es manchmal schwierig, etwas so viel schneller zu machen wie eine Bibliothek mit komplettem Neustart. Ich habe in einem aktuellen Projekt all diese Tools analysiert und mich teilweise aus diesem Grund für ArkType entschieden. Außerdem fühlte sich die TypeScript-Nutzung besser an.
Wir verwenden Zod nur für Formularvalidierung, daher denke ich: „Warum ist das wichtig?“ Vielleicht gibt es Fälle, in denen Leute Dinge wie Input-Messages für High-Throughput-APIs validieren, wodurch Performance wichtiger wird.
Trotzdem glaube ich nicht, dass ich von Zod wechseln werde.
Glückwunsch an das Zod-Team zum neuen Release. Auch auf die Gefahr hin, zu negativ zu klingen: Bei der Zahl der Breaking Changes im Migrationsleitfaden läuft es mir kalt den Rücken hinunter.
Für Projekte, die stark von Zod abhängen, wirkt das wie eine mühsame Aufgabe, die viel Konzentration und Zeit von Entwicklern erfordert. Das kann ich besonders gut nachvollziehen, weil ich beruflich einige 4–5 Jahre alte Frontend-Projekte gewartet habe.
Große React-Projekte hängen typischerweise von vielen Bibliotheken ab, und wenn jede davon große Änderungen bringt, noch dazu mit unzureichender Dokumentation, wird man sehr schnell überwältigt. Das ist einer der Aspekte, die ich an der Arbeit mit JavaScript am meisten hasse: Alles aufeinander abzustimmen und dauerhaft reibungslos am Laufen zu halten, fühlt sich wie ein endloser Anstieg an.
Ehrlich gesagt war es ein Albtraum, und ich wünschte, wir hätten es stattdessen mit Django gebaut. Entgegen meinen Erwartungen gehörte die Migration von Tailwind 3 → 4 zu den schmerzhaftesten.
mini-Edition entschieden. So wird eine schrittweise Migration einfacher, ohne den Paketmanager anzufassen.Nutzer, die sich nicht für die
mini-Edition interessieren, müssen sich darum nicht kümmern. Allerdings sind die Tree-Shaking-Vorteile dermini-Edition so groß, dass sie die Entwicklung von Alternativen angetrieben haben, und Zod musste das annehmen oder an Bedeutung verlieren.Als Full-Stack-Entwickler, der selbst ein SaaS mit Tausenden Nutzern in Produktion betreibt, merke ich manchmal erfreut, wie viele Probleme ich gar nicht kenne, weil ich mich entschieden habe, keine SPA zu bauen und kein JS-Frontend-Framework zu verwenden.
Ich habe nicht einmal daran gedacht, dass man etwas wie Zod/ArkType brauchen könnte, höre zum ersten Mal davon und werde es auch nicht verwenden.
Es ist erstaunlich, wie viel Aufwand, Komplexität und Tooling in den Bau einer SPA fließen. Wenn man sich entscheidet, keine SPA zu bauen, existieren ganze Problemklassen einfach nicht. Stattdessen nutzt man den Browser so, wie er ursprünglich gedacht war: mit vollständigen Seiten-Reloads und Fokus auf Backend-Entwicklung, und fügt gelegentlich mit einem reinen Backend-Framework wie Laravel Livewire etwas Reaktivität hinzu.
Alles ist einfacher, von Zugriffskontrolle über Validierung bis hin zu State Management. Die App ist schnell, responsiv, modern, SEO-freundlich und bedient Tausende Nutzer in Produktion.
Am Ende gibt es irgendwo ein Schema. Es kann im Datenbanksystem definiert sein oder in ORM-Modellen. In großen Projekten können Schemas im Datenbanksystem oder ORM jedoch sehr schwierige Probleme verursachen, daher verwenden wir Zod und Protobuf. Ich denke, Protobuf könnte ebenfalls vollständig durch Zod oder etwas Ähnliches ersetzt werden.
Der britische Post-Office-Skandal betraf ein IT-System namens Horizon: https://en.wikipedia.org/wiki/British_Post_Office_scandal
Nachdem ich die Details gelesen habe, scheint mir, dass Schema-Validierung wie bei Zod dazu hätte beitragen können, diesen Skandal zu verhindern. Auch der technische Anhang der Gerichtsunterlagen zur Sammelklage erwähnt das Fehlen der Nutzung von Schemas: https://en.wikipedia.org/wiki/Bates_%26_Others_v_Post_Office...
Im Moment klingt es so, als würdest du defensiv jede Menge
if-Anweisungen schreiben. Schlimmer noch: Vielleicht verlässt du dich nur auf clientseitige HTML-Formularvalidierung.Ich bin kein Experte und daher vorsichtig, aber ich dachte, JSON Schema könnte eine gute Wahl sein, weil es schemabasiert ist und sich Validatoren auch in anderen Sprachen als TypeScript implementieren lassen.
https://ajv.js.org ist eine dieser JSON-Schema-Bibliotheken. Mich würde interessieren, wie sie im Vergleich zu Zod abschneidet.
Wenn man möchte, kann man es auch als JSON-Transformer verwenden. Man kann zum Beispiel ein Schema schreiben, das einen String entgegennimmt, prüft, ob er ein ISO-Datumsstring ist, und ein
Date-Objekt ausgibt.Der wichtige Unterschied sind Preprocessing und
refine. In Zod kann man vor der Validierung Callbacks bereitstellen; das ist sehr nützlich, lässt sich aber nicht in JSON ausdrücken. Zum Beispiel ist es überraschend oft hilfreich, vor der DatumsvalidierungMM/DD/YYYYinDD/MM/YYYYumzuwandeln.Für die Validierung kann man AJV verwenden oder das eigene Schema-Validierungssystem von TypeBox. Letzteres ist deutlich schneller, unterstützt aber nur synchrone Validierung; AJV bietet Optionen für asynchrone Validierung, etwa Datenbankprüfungen.
Die negativen Reaktionen rund um dieses Thema überraschen mich.
Ich habe eine frühe Version von Zod v4 getestet und mochte die neue API, war aber sehr besorgt darüber, wie der Migrationspfad aussehen würde. Ich hatte sogar überlegt vorzuschlagen, es unter einem ganz neuen Paketnamen zu veröffentlichen.
Der Ansatz des Autors ist aber clever. Er ermöglicht Leuten wie mir, v4 sofort einzuführen, ohne darauf warten zu müssen, dass alle Abhängigkeiten aktualisiert werden.
Ich habe gerade erst begonnen, Zod in einem neuen Projekt einzuführen, und der Zeitpunkt hätte nicht besser sein können.
Nach dem, was ich jetzt sehe, hätte ich für den Umstieg auf v4 wirklich sehr viel ändern müssen.