1 puntos por GN⁺ 2025-05-20 | 1 comentarios | Compartir por WhatsApp
  • Lanzamiento de la versión 4 de Zod, una librería de declaración y validación de esquemas, ya en versión estable con importantes mejoras de rendimiento y funciones muy solicitadas desde hace tiempo
  • Hubo grandes mejoras en velocidad y tamaño del bundle, y la nueva versión mini (v4-mini) reduce drásticamente el tamaño del bundle
  • Se agregaron un nuevo registro de metadatos, conversión a JSON Schema y capacidad de inferencia de tipos recursivos
  • Se reforzó la experiencia de desarrollo con personalización de mensajes de error y un sistema de locales multilingüe
  • También aumenta su extensibilidad con la incorporación de un subpaquete core que podrá aprovecharse para construir librerías en el futuro

Introducción a Zod 4

Guía sobre este lanzamiento principal

  • Tras un año de desarrollo activo, Zod 4 se lanzó como versión estable
  • Su desarrollo contó con el apoyo de la OSS Fellowship de Clerk
  • Actualmente se distribuye en paralelo con Zod 3, lo que facilita una migración gradual hacia Zod 4
  • Se puede consultar información detallada sobre algunos cambios incompatibles en la Migration guide

Contexto de crecimiento

  • En comparación con Zod 3, lanzado en 2021, Zod 4 creció exponencialmente en estrellas de GitHub y descargas semanales
  • Zod 4 es mucho más rápido, más ligero y mejora la eficiencia del compilador de TypeScript
  • Se resolvieron 9 problemas principales muy solicitados durante mucho tiempo

Benchmarks y rendimiento

  • Mejora de velocidad:
    • Parsing de cadenas: 14.71 veces más rápido
    • Parsing de arreglos: 7.43 veces más rápido
    • Parsing de objetos (safeParse): 6.5 veces más rápido
  • El repositorio incluye scripts para ejecutar benchmarks directamente
  • Gracias a una estructura genérica mejorada, el rendimiento de compilación mejora 10 veces al encadenar métodos como .extend() y .omit()
  • La velocidad de compilación de TypeScript mejora notablemente en esquemas y bases de código grandes

Tamaño del bundle y Zod Mini

  • El tamaño base del bundle se redujo en 57%, por lo que v4 ofrece un tamaño 2.3 veces menor que v3
  • zod/v4-mini ofrece una API basada en funciones y compatible con tree shaking, reduciendo el bundle hasta en 85%
  • La documentación oficial detalla las diferencias de API entre core y v4-mini
  • La estructura fue diseñada para que los bundlers eliminen fácilmente los métodos no utilizados

Registro de metadatos y soporte para JSON Schema

  • Es posible registrar y gestionar typed metadata en los esquemas con tipado fuerte
  • El registro global (z.globalRegistry) ofrece manejo de metadatos compatibles con JSON Schema e inclusión automática
  • .meta() y .describe() facilitan la documentación de esquemas
  • Con .toJSONSchema() se puede convertir un esquema al formato JSON Schema, reflejando automáticamente los metadatos

Inferencia automática de tipos recursivos

  • Es posible definir e inferir de forma natural tipos de objetos recursivos y tipos mutuamente recursivos sin type casting adicional
  • La usabilidad mejora considerablemente frente a los patrones de Zod 3
  • Incluso en tipos recursivos y mutuamente recursivos, se pueden usar todas las funciones de métodos del esquema

Tipo de archivo y funciones de validación

  • El nuevo tipo file() permite validar instancias de File
  • Ofrece validación de diversas restricciones de archivo, como tamaño (min, max) y tipo MIME

Mensajes de error y sistema de locales

  • La API global de locales (z.locales) permite soporte multilingüe para mensajes de error
  • La función oficial z.prettifyError permite formatear errores de forma amigable para el usuario

Funciones de formato y template literals

  • Los formatos de cadena existentes (email, etc.) se promovieron a funciones de nivel superior, mejorando la legibilidad y el tree shaking
  • Se ofrecen varias opciones de expresiones regulares para email para cubrir distintos requisitos de validación
  • Soporte para tipos de template literal: permite implementar fácilmente patrones de cadenas y combinaciones complejas que pueden expresarse en el sistema de tipos

Nuevos formatos numéricos y bigint

  • Soporte para tipos enteros y de punto flotante de ancho fijo (int32, uint64, etc.)
  • Es posible generar esquemas con restricciones mínimas y máximas añadidas automáticamente dentro de rangos seguros

Introducción a z.stringbool

  • Permite parsing de booleanos basados en cadenas (yes, no, etc.) y también soporta parsing estilo variables de entorno
  • Los valores truthy/falsy se pueden personalizar

Unificación de la API de personalización de errores

  • Un parámetro error unificado ordena la estructura de los mensajes de error y la lógica de manejo
  • Las APIs anteriores relacionadas con errores (message, invalid_type_error, errorMap) quedaron deprecated

Otras mejoras clave

  • Las discriminated unions soportan diversos esquemas, anidación y combinaciones
  • .literal() permite varios valores al mismo tiempo
  • Las validaciones personalizadas como .refine() se integran de forma más intuitiva
  • Con .overwrite() relacionado con transformaciones, es posible hacer posprocesamiento sin cambiar el tipo transformado

Extensibilidad de librerías y nuevo core

  • Con zod/v4/core, la funcionalidad central se separa en un subpaquete independiente, lo que permite integración y expansión en distintas librerías y plataformas
  • Se ofrecen documentación guía y ejemplos de extensión para creadores de librerías

Cierre

  • Zod 4 se consolida como una librería de validación de datos con grandes mejoras en seguridad de tipos, rendimiento, extensibilidad y experiencia de desarrollo
  • Se anticipan futuras publicaciones de diseño y más actualizaciones
  • Se prepara un amplio soporte tanto para usuarios existentes como para creadores de librerías

Que tengas una feliz experiencia de parsing
— Colin McDonnell @colinhacks

1 comentarios

 
GN⁺ 2025-05-20
Opiniones de Hacker News
  • El propio autor pidió que compartieran sus opiniones y dio una explicación detallada sobre la forma de gestionar las versiones, subrayando que npm no es adecuado para manejar una situación como la de Zod; mencionó que muchísimas librerías importan y usan directamente interfaces/clases de Zod, y que si Zod cambia de versión principal, todas esas librerías tendrían que adaptarse al mismo tiempo, lo que podría provocar una explosión de versiones. Explicó que, de forma similar a Go, para los cambios incompatibles se usa el enfoque de agregar una nueva ruta de subpath, y que en un entorno de TypeScript se puede dar soporte simultáneo a "zod/v3" y "zod/v4" con solo zod@^3.25.0, ofreciendo así una ruta de actualización gradual para el usuario final.

    • Agradece las contribuciones a Zod y dice que tiene especial expectativa por la mejora en rendimiento de tsc y en las discriminated unions. Entiende bien el esquema de versionado, pero propone que para usuarios como él, que no se preocupan por conflictos de dependencias transitivas, también estaría bien ofrecerlo simplemente como un paquete 4.0.0. Cambiar los imports a "zod/v4" podría generar ruido en el código y molestias adicionales, como conflictos con los auto-imports del IDE. Aun así, considera que en general es una actualización muy prometedora y agradece el trabajo.

    • Dice que está viendo el artículo desde el celular y pide disculpas si se le pasó algo; pregunta si la mayor molestia relacionada con .optional() está incluida en la solución de los issues top 9/10 de esta vez. Menciona que Zod es tan bueno que lo sigue usando aunque tenga incomodidades, y agradece que sea una librería excelente.

    • Agradece poder eliminar mucho código manual y hacks con la nueva versión de Zod. Comenta que personalmente usa zod-key-parser para reducir typos, y pregunta por qué una función así no viene integrada en la librería, si se considera fuera de alcance o si simplemente aún no se ha implementado; comparte discusiones abiertas relacionadas.

    • Enfatiza que minimizar el dolor a corto plazo muchas veces es lo mejor, y menciona como ejemplo el caos de la migración de Python 2/3.

    • Comparte que tuvo muchas dificultades al usar al mismo tiempo tipos recursivos y formas de discriminated union, por ejemplo al incluir XML dentro de JSON, y espera que con esta actualización la situación mejore bastante.

  • Expresa dudas sobre el import zod/v4-mini, y supone que eso más bien podría aumentar el tamaño del bundle. Como la documentación oficial dice que zod/v4 es lo recomendado en la mayoría de los casos, los desarrolladores de apps usarían zod/v4, pero si quienes escriben librerías agregan también zod/v4-mini para reducir tamaño, teme que ambos terminen en el bundle y haya duplicación. Pregunta si este problema podría reducirse si zod/v4 fuera un wrapper de zod/v4-mini.

  • Para facilitar la migración a Zod 4, se introdujo una forma en la que v3 y v4 se ofrecen al mismo tiempo dentro de zod@3.25, y critica que, combinado con las limitaciones de manejo de dependencias en npm, eso obligó a hacer que v4 pareciera v3. Señala que el sistema de peer dependencies de npm es ineficiente.

    • El propio autor vuelve a explicar la estrategia de versionado al estilo Golang con subrutas añadidas; reconoce que por las características de npm es difícil introducir esto en el ecosistema de Zod, pero destaca la ventaja de soportar simultáneamente v3 y v4 y ofrecer una migración gradual.

    • No está necesariamente de acuerdo con la opinión previa de que, porque peer dependencies está roto, se disfrazó v4 como v3. Recalca que esto es una medida para permitir una migración gradual: se reemplaza poco a poco por zod/v4 y luego se completa el upgrade total a v4.

    • Dice que mucha gente lo critica, pero que en realidad más que una limitación esencial de npm, fue una decisión práctica para permitir que una librería con cambios grandes pudiera actualizarse de manera gradual.

    • Comenta que quizá tiene sesgo por haber usado npm durante mucho tiempo, pero le da curiosidad saber cuál sería una mejor forma de dar soporte gradual en vez de forzar un salto grande de v3 a v4 de una sola vez.

    • Menciona que ya vio grandes mejoras con la beta de Zod 4, pero que en un codebase grande no ha podido hacer bien el upgrade por lo difícil que ha sido configurar la resolución de módulos. Dice que le gustaría que también lo hubieran lanzado solo como versión principal, sin esa capa legacy; comparte la explicación del autor sobre evitar la “explosión de versiones”, aunque cree personalmente que mantener soporte de v3 en paralelo sí puede amortiguar el impacto.

  • Pregunta cómo modelar los tipos de respuestas del servidor cuando el tipo que devuelve cambia según el endpoint, o cuando algunos campos pueden venir como null, como en usuarios anónimos; comenta que al crear varias funciones como normalizeUser o normalizePost, cada vez se vuelve más difícil de mantener, y pide experiencias sobre cómo se resuelve esto en trabajo real.

    • Propone resolverlo con un ejemplo de discriminated union: definir como objeto la parte común del esquema y luego extenderla según cada caso específico. Aconseja que, aunque si hay muchísimos casos igual puede volverse complejo, al menos con un schema validator se puede mantener de forma más sistemática.

    • Dice que idealmente lo mejor es definir la estructura de tipos de User en una sola fuente, por ejemplo como una discriminated union. Asumiendo un backend en Python, propone una estructura con varios modelos de Pydantic + union y generación de tipos para el cliente TypeScript mediante OpenAPI/GraphQL code generation.

    • Comenta que podría responder mejor si conociera un ejemplo real de uso, pero explica que si al tipo union se le agrega una propiedad discriminante (por ejemplo, "user_type"), se facilita el acceso a campos individuales, porque el sistema de tipos puede reconocer qué propiedades corresponden según el caso.

    • Aconseja firmemente que el servidor exporte directamente los tipos; volver a escribir manualmente tipos separados en el cliente es ineficiente. Explica que en un backend Python se puede usar Pydantic para generar automáticamente la especificación OpenAPI y a partir de ahí generar tipos para el cliente TypeScript.

    • Menciona que GraphQL está diseñado justamente para este tipo de casos, y que con librerías GraphQL para TypeScript se puede inferir automáticamente la forma del resultado de una query y generar tipos de respuesta dinámicos según los campos seleccionados.

  • Menciona que, aunque Zod 4 mejoró, ArkType sigue siendo muy superior en velocidad. Dice que en librerías existentes hay límites de rendimiento por mantener compatibilidad hacia atrás y preservar la sintaxis, y que, tras analizar su propio proyecto, eligió ArkType por rendimiento y usabilidad con TypeScript.

    • Dice que vio las métricas de velocidad de ArkType, pero se pregunta en qué impacta eso en la práctica. Le parece que en situaciones normales, como validación de formularios, no influye tanto, así que pregunta si se usa en entornos sensibles al rendimiento, como validación de entrada en APIs ultrarrápidas.

    • Comenta que ArkType no estaba incluido en su investigación, aunque sí lo estaba buscando pensando en usabilidad con TypeScript. Aun así, no planea migrar desde Zod.

    • Dice que su experiencia usando ArkType fue bastante difícil y que prefiere Zod porque le resulta más usable.

    • Pregunta si hubo alguna razón especial para elegir ArkType por encima de TypeBox.

  • Felicita al equipo de Zod por el nuevo lanzamiento y dice que, viendo la cantidad de cambios incompatibles acumulados en la guía de migración, le preocupa que para proyectos grandes que dependen mucho de Zod esto sea una carga pesada y difícil de gestionar. Desde su experiencia manteniendo proyectos frontend antiguos, lamenta que cada librería tenga cambios grandes y poca documentación, y expresa frustración con la dirección actual de la evolución en JS.

    • Dice que opera varias apps grandes de Next.js y que en el último año ha pasado por cambios grandes y difíciles como Next.js 14→15, Next.js pages→app router, React 18→19, Eslint 8→9 y Tailwind 3→4; comenta que fue realmente agotador y que incluso llegó a pensar que habría sido mejor construirlo en Django. Recuerda especialmente que la migración de Tailwind 3→4 fue, inesperadamente, la más dolorosa.

    • Explica que para aliviar este problema se introdujo la estrategia de ofrecer al mismo tiempo la edición mini, para facilitar una transición gradual, y que desde el punto de vista de la optimización para tree-shaking, incorporar mini también era inevitable para competir con alternativas.

    • Propone que, usando herramientas como los LLM, la migración puede hacerse sin demasiada dificultad.

  • Menciona que Zod es mucho mejor que otras alternativas existentes, pero que en desarrollo web sigue siendo una realidad tener que describir la misma estructura de datos de varias maneras: validación de input en JS, especificación de API con Swagger, y definiciones separadas en servidor y cliente, todo muy repetitivo y engorroso.

    • Lamenta que TypeScript insista en ser solo una herramienta de chequeo estático; no dice que quiera validación en runtime, pero sí desearía poder reutilizar fácilmente hacia afuera la información de tipos de clases, funciones y objetos. Actualmente muchas herramientas tienen que definir sus propios modelos y builders, por lo que la duplicación es inevitable. Comparte que el proyecto de estandarización Standard Schema parece estar integrándose con las principales librerías de validación, aunque la expansión hacia especificaciones de API y ORM todavía está en etapas iniciales.

    • Enfatiza que la clave de estas herramientas es que uno puede definir algo una sola vez y propagar la type safety a toda la aplicación; se puede tomar el schema de Zod como una especie de fuente única de verdad.

    • Agrega que entre quienes se quejan de este esquema tan enredado, muchos también muestran rechazo cuando se propone unificarlo todo con TypeScript (incluido Zod).

    • Señala que todas las APIs y sistemas están siempre cambiando y experimentando; aunque la realidad de tener más capas complejas es una desventaja, desde la perspectiva de “mientras el proyecto funcione bien”, al final eso solo termina creando más trabajo.

    • En general, dice que se puede usar type safety end-to-end con algo como trpc, pero para eso frontend y backend tendrían que unificarse en TypeScript, y además resulta difícil usarlo en plataformas no web, como mobile, lo que marca un límite práctico en el trabajo real.

  • Dice que no es experto, pero que como JSON-Schema está basado en schemas, le parece una buena opción porque permite implementar validadores también en otros lenguajes además de TypeScript. Pregunta por la comparación con Zod usando como ejemplo librerías como ajv.js.org.

    • Explica que Zod puede validar no solo formas JSON, sino objetos completos de JS, como fechas o instancias de clases, es decir, datos que no se pueden representar en JSON. También puede usarse en el proceso de conversión desde JSON, escribiendo schemas basados en strings y, por ejemplo, validando y transformando un ISO date string en un objeto Date.

    • Dice que Zod 4 ahora soporta convertir schemas de Zod a JSON-Schema (antes hacía falta una librería externa). Destaca que una gran diferencia de Zod son las funciones preprocess/refine, porque permiten añadir callbacks antes de validar, por ejemplo para convertir MM/DD/YYYY a DD/MM/YYYY y luego validarlo; remarca que esto no es posible en JSON-Schema.

    • Comenta que JSON-Schema también es una buena opción, y que en ese caso TypeBox sirve bien para generarlo. Se puede usar avj o incluso un sistema de validación propio; el propio suele ser más rápido, pero es solo síncrono, mientras que avj también permite validación asíncrona, lo que resulta ventajoso cuando se necesita validación más profunda.

    • Dice que si se quiere usar en varios lenguajes, JSON-Schema es lo más universal, y que si además se envuelve con OpenAPI, se puede generar automáticamente documentación de la API, lo cual es una ventaja.

  • Comenta que recién estaba empezando a adoptar Zod en un proyecto nuevo y que el timing de este release le cayó perfecto; si hubiera tenido que migrar a v4 según el plan original, habría necesitado muchos cambios, así que el momento resultó ideal.

  • Dice que le sorprende ver más opiniones negativas de las que esperaba. Cuando probó versiones iniciales de v4, le gustó la nueva API, pero le preocupaba la ruta de migración, e incluso pensó en proponer que saliera con otro nombre de paquete; sin embargo, considera que la forma elegida por el autor resolvió el problema de manera excelente. Gracias a eso, se puede adoptar v4 de inmediato sin esperar a que se actualicen las dependencias.

    • También piensa que en áreas como validación no hay forma de migrarlo todo de una sola vez, así que evalúa que el enfoque actual es, en términos realistas, el mejor posible.