Saltar al contenido principal
Desarrollo Móvil

OpenAPI TypeScript: Generar Tipos, Clientes y Validación

Aprende cómo funciona la generación de OpenAPI TypeScript de principio a fin. Genera tipos, conecta clientes, valida en tiempo de ejecución y envía de manera segura desde CI.

Martin Donadieu

Martin Donadieu

Gerente de Contenido

OpenAPI TypeScript: Generar Tipos, Clientes y Validación

Puedes identificar normalmente el momento en que un API pipeline comienza a engañar al equipo. Un esquema cambia, los tipos generados se actualizan sin quejas, la PR pasa por verde, y luego alguien en la parte del frente sigue leyendo la forma de respuesta antigua porque el wrapper ocultó el error. Eso es el problema de OpenAPI TypeScript, no si un generador puede arrojar interfaces.

La pregunta útil es más difícil. ¿Cuál es el contrato que deseas entre esquema, transporte y validación, y qué partes deberían fallar rápidamente en tiempo de compilación en lugar de filtrarse en tiempo de ejecución? Una vez que enmarques OpenAPI TypeScript como una elección de pipeline, las compensaciones se vuelven mucho más claras, y las herramientas dejan de fingir ser la solución completa.

Índice

¿Por qué los Tipos Generados No Son lo Mismo que un API Seguro

Un compañero de equipo mergea una PR que agrega un campo de respuesta opcional. El archivo generado se actualiza limpiamente, la diferencia parece aburrida, y todos siguen adelante. Luego la interfaz de usuario sigue leyendo una forma más antigua a través de un wrapper manual que fue ‘temporalmente’ cast con as anyy la producción comienza a comportarse como si el contrato nunca hubiera cambiado.

Esos son los peligros con los tipos generados. TypeScript solo puede proteger el code que consume los tipos generadosy solo si la capa de transporte no borra el contrato de nuevo. El lado de OpenAPI te da un esquema, no una garantía de que todos los llamadores lo respeten. La discusión sobre comprender las conexiones API es útil aquí porque empuja la conversación lejos de una herramienta única y hacia cómo se conectan los sistemas.

¿Dónde se esconden los fracasos?

Los puntos de ruptura más comunes son aburridos, no exóticos. El desplazamiento de esquemas ocurre cuando la especificación OpenAPI y el servicio desplegado dejan de coincidir. La cobertura parcial se manifiesta cuando una especificación solo modela el camino feliz, mientras que la aplicación depende de casos de borde no documentados. Los envoltorios manuscritos son a menudo donde se debilitan los tipos, especialmente cuando alguien quiere “avanzar rápido” y utiliza any o un cast de respuesta suelto.

Regla práctica: si el envoltorio puede mentir, el generador no puede salvarte.

There también existe una brecha de tiempo de ejecución. Los tipos de TypeScript desaparecen después de la compilación, por lo que no pueden rechazar JSON malformado que llega por cable. La red no se preocupa por lo que su editor ha inferido, y eso es por qué un cliente generado es solo una capa en una pipoteca más segura API.

La cuestión operativa más amplia es la seguridad y la disciplina de contrato, no solo la conveniencia del desarrollador. Si desea una vista estructurada de cómo API los contratos se ajustan a un ciclo de vida de aplicación más grande, esta guía interna sobre API estándares de seguridad para la conformidad con la tienda de aplicaciones es un compañero útil.

La forma madura de pensar sobre openapi tiposcript es esta. Le da una conexión estricta de esquema a tipos, que es excelente, pero no valida las solicitudes, impone la forma de carga de pago en tiempo de ejecución ni detiene un wrapper descuidado de socavar todo. El generador es el 20 por ciento fácil. El resto es el diseño de la pipoteca, y eso es donde los equipos ganan confianza o acumulan confianza falsa.

Generación de tipos de TypeScript a partir de una especificación OpenAPI

Captura de pantalla de https://openapi-ts.dev

La configuración más ligera pero útil es usualmente la que sobrevive a los cambios reales de repositorio. Mantenga la especificación OpenAPI en el mismo repositorio, genere un archivo de tipos comprometido y haga visible la deriva en CI en lugar de confiar en alguien que recuerde un paso de refresco. Una orden como npx openapi-typescript ./openapi.yaml -o ./src/types/api.d.ts dice que obtiene un archivo de salida determinista que los revisores pueden inspeccionar como cualquier otro cambio de código.

Las banderas que realmente importan

The bandera de salida importa porque hace explícito el artefacto generado. -o es útil cuando deseas que los tipos generados preserven la intención readonly en la salida, y --immutable mantiene las diferencias estables cuando cambia el orden del esquema sin significado semántico. --alphabetize importa cuando tu equipo prefiere enums en la superficie generada en lugar de uniones. --enum La documentación del proyecto es clara sobre el alcance, es un

generador de tipos , no una capa de tiempo de ejecución o de solicitud, y esa limitación ayuda cuando deseas una configuración de tipo ligera.Su repositorio también muestra el modelo de mantenimiento detrás de la herramienta, lo que es parte de por qué la herramienta de código abierto puede mantenerse en producción cuando los documentos y las versiones permanecen activos, como se discute en el caso para el mantenimiento de código abierto. Una lectura práctica de esa postura es el repositorio y la documentación de GitHub repository and CLI documentation.

__CAPGO_KEEP_1__ y la integración de generación de cables package.json Así, el comando vive junto a los demás scripts de construcción, y se ejecuta cada vez que cambia la especificación. En CI, regenera el archivo y falla si git diff muestra desfase. Eso convierte los cambios de contrato en trabajo de revisión visible en lugar de riesgo silencioso en tiempo de ejecución.

El lado del esquema importa tanto como la línea de comandos. El proyecto recomienda compilerOptions.noUncheckedIndexedAccess así que additionalProperties se convierta T | undefined, que fuerza un índice más seguro en los sitios de llamada. También recomienda utilizar oneOf por sí solo en lugar de mezclarlo con composición adicional, y mantener $defs a la raíz cuando la colocación es ambigua, porque las definiciones mal colocadas pueden desaparecer del resultado generado. Un detalle más ahorra tiempo más adelante, openapi-typescript nunca producirá any, por lo que la falta de detalle del esquema se hace visible temprano en lugar de estar oculta bajo tipos permisivos.

Mantén la especificación explícita, o el generador te devolverá la ambigüedad con fidelidad.

El flujo de trabajo que perdura es sencillo. Coloca la especificación bajo control de versiones, regenera en construcción, comienza el archivo generado y deja que el verificador de tipos se queje antes de que alguien mezcle una incompatibilidad. Eso te da una frontera de contrato estable para el resto de la canalización.

Elegir entre tipos puros, clientes completos y sin código generado

Patrón Tiempo de compilación Archivos de salida Peso del paquete Mejor ajuste
Tipos puros con un envoltorio delgado Rápido Pocos Bajo Equipos que quieren control y superficie de tiempo de ejecución pequeña
Generación de código de cliente completo Más lento Muchos Más alto Los equipos que desean una entrega rápida y operaciones generadas automáticamente
No hay constructores de solicitudes de generación de código Rápido Ninguno o mínimo Bajo Aplicaciones de un solo códigobase que prefieren la lógica de transporte escrita a mano

La elección no es realmente “qué herramienta gana”. Es qué forma de pipeline se ajusta a tu repositorio, tu equipo y cuánto giro ve el API. En un benchmark de 2025 alrededor de una gran especificación OpenAPI de unos 75,000 líneas, 2 MB y aproximadamente 1,200 operaciones, openapi-typescript salida generada en unos 1.5 segundos en promedio, comparado con aproximadamente 8.0 segundos para @hey-api/openapi-ts, 5.5 segundos para Orval, y 18.1 segundos para Kubb, mientras también produce un archivo de salida único en lugar de 16 para hey-api, 2,719 para Orvaly 3,877 para Kubb (detalles de benchmark).

Los tipos puros favorecen el control

Una configuración de tipos puros se adapta bien a una capa de solicitudes manuales porque puedes mantener el tiempo de ejecución pequeño y la superficie API aburrida. Eso importa en front-end sensibles a empaquetadores y en aplicaciones donde un equipo posee tanto la especificación como el consumidor. Si necesitas un recordatorio de que la experiencia del desarrollador no es solo azúcar de sintaxis, el ángulo de la experiencia del desarrollador es más fácil de juzgar cuando tu cliente code es corto, obvio y revisable.

Los clientes completos favorecen la velocidad de transferencia de mano

openapi-generator, hey-api, Orvaly Kubb todos tratan de hacer más que los tipos. Eso puede ser útil cuando quieres que los métodos de solicitud, los modelos y la canalización generen juntos, especialmente en una gran transferencia de mano entre equipos de backend y frontend. El costo es obvio en el benchmark anterior, más archivos generados, más superficie de tiempo de ejecución y más espacio para la fricción de compilación a medida que la especificación crece.

No hay generación de código favorece los refactores locales

Los constructores de solicitudes tipados y fetch Los wrappers funcionan bien cuando un código base controla ambos extremos de la forma y los cambios en la API están coordinados estrechamente. El lado negativo es la disciplina de mantenimiento. Cuanto más equipos y repositorios estén entre el productor y el consumidor, más probable es que una capa de solicitudes manuales se desvíe a menos que se impongan pruebas de contrato de manera agresiva.

No es un punto de decisión ideológico. Si su presupuesto de paquete es ajustado, los tipos puros son atractivos. Si su equipo quiere una scaffolding máxima y puede absorber la salida, los clientes completos reducen el tiempo de configuración. Si quiere partes móviles mínimas y puede mantener el contrato cerca, los constructores de solicitudes sin código pueden ser la opción interna correcta.

Conectar un Cliente delgadamente Tipado alrededor de Fetch o Axios

Un diagrama que ilustra un proceso de Wrapper de Cliente Tipado utilizando definiciones de TypeScript API generadas para solicitudes web.

Un wrapper delgado es donde el generador se detiene y comienza su aplicación code. El wrapper debería exponer una función por operación, aceptar parámetros y objetos de consulta tipados y enviar la llamada a fetch o una instancia inyectada axios sin intentar ser demasiado inteligente. En la mayoría de los entornos de producción, esa capa permanece alrededor 30–60 líneas porque los tipos generados ya llevan la mayoría de la forma.

Este es el modelo mental que se mantiene:

  • Los parámetros de ruta permanecen tipados para que /users/{id} no se puede llamar sin un id.
  • Los objetos de consulta permanecen tipados de modo que los filtros opcionales no se conviertan en sopa de cadenas.
  • Los cuerpos de respuesta permanecen tipados de modo que el parsing de code puede confiar en la forma estrecha que espera.

Un wrapper como ese es intencionalmente aburrido. No debe inventar reintentos, transformaciones o políticas de autenticación si esos pertenecen a otro lugar. Debe mover la solicitud desde una operación tipada hasta la capa de transporte y luego devolver el resultado tipado hacia arriba.

Mantenga el wrapper aburrido y liviano en dependencias, o cada cambio futuro en el generador se propagará a tu aplicación.

El fracaso común es parchear las incompatibilidades con as any cuando los tipos generados no se alinean con la firma de firma del wrapper antiguo. Eso compra una compilación verde y una aplicación frágil. También oculta la ruptura de contrato que querías que el generador revelara.

Para equipos que prefieren Axios, el patrón es el mismo, solo cambia la implementación de transporte. Para equipos que quieren una navegación más simple en el lado del navegador code fetch a menudo es suficiente. La parte importante es que la función de solicitud acepta el tipo de ruta generado y devuelve una respuesta tipada, no un objeto con forma suelta que se masajea más tarde.

Si utilizas bien esta juntura, typescript abierto dame una división de trabajo limpia. El esquema vive en la especificación, el transporte vive en el envoltorio, y la aplicación ve operaciones tipadas en lugar de solicitudes ad hoc code.

Agregar validación de tiempo de ejecución con zod, ajv o io-ts

Los tipos de TypeScript desaparecen en tiempo de ejecución, y la red no se preocupa por la confianza del editor. Eso es por qué el patrón seguro no es 'generar tipos y esperar', es 'generar tipos, luego validar en el borde donde entra el dato no confiable en la aplicación'. El esquema generado sigue siendo la fuente de verdad, y las bibliotecas de validación como zod, ajvy io-ts manejan los controles de límites que los tipos de tiempo de compilación no pueden.

Valida donde entra el dato

Para aplicaciones de React, el borde suele estar justo después de que se resuelve la solicitud y antes de que el payload ingrese al estado. Para servidores, es antes de que el payload se escriba en una base de datos o se le entregue a una regla comercial. La regla es simple, mantén la validación cerca del borde y no disperses comprobaciones manuales a través de características code.

Una zod forma puede reflejar la forma de respuesta generada sin reemplazarla:

import { z } from "zod";

const WeatherForecastSchema = z.object({
  date: z.string(),
  temperatureC: z.number(),
  summary: z.string().nullable(),
  temperatureF: z.number().optional(),
});

Ese ejemplo valida los campos que el esquema marcó como opcionales, y mantiene la comprobación de tiempo de ejecución alineada con lo que produjo el generador. ajv es una elección fuerte cuando deseas una alta tasa de JSON Schema de validación en el servidor, mientras io-ts still se adapta a los equipos que ya viven en el fp-ts estilo de composición.

El gran error es validar demasiado tarde. Si el payload cruza a tu aplicación primero, el sistema de tipos ya ha sido bypassado y el bug tiene un lugar para esconderse. Una guía breve sobre pruebas unitarias para JavaScript se complementa bien con este enfoque, porque tanto las pruebas unitarias como la validación de límites funcionan mejor cuando capturan malas suposiciones temprano.

La capa limpia es predecible. OpenAPI TypeScript genera el contrato, el validador verifica el payload de tiempo de ejecución y tu aplicación code solo ve los datos que sobrevivieron a ambos pasos. Eso es un límite mucho mejor que confiar en un tipo estático para policía una respuesta no confiable.

Colocar Generación, Validación y Pruebas de Contrato en CI

Captura de pantalla de https://github.com

Una canalización que dura convierte el contrato en una puerta, no una sugerencia. Regenera tipos, falla en el desplazamiento, ejecuta tsc --noEmit, y ejercita la forma API contra una herramienta de contrato o mock antes de la fusión. Si pinzas la versión del generador en package.jsondos ingenieros no pueden producir accidentalmente diferentes salidas a partir de la misma especificación.

Una forma simple de GitHub Actions

Un flujo de trabajo práctico se parece a esto:

  1. Extraer la especificación desde el repositorio o fuente generada.
  2. Regenerar los tipos.
  3. Fallar el trabajo si git diff muestra cambios.
  4. Ejecutar tsc --noEmit.
  5. Ejecutar una prueba de contrato contra un servidor de prueba como Prism o una comprobación respaldada por Spectral.

La diferencia clave entre las pruebas de contrato y las pruebas de snapshot es el alcance. Las snapshots a menudo te dicen que el archivo ha cambiado. Las pruebas de contrato te dicen si la forma sigue comportándose como la especificación dice que debe hacerlo.

Un servidor de prueba es especialmente útil cuando el trabajo de backend y frontend están separados por límites de tiempo o equipo. Proporciona a los consumidores code una superficie API predecible mientras aún se comprueba el contrato real en lugar de una fijación fija. Guía de configuración de integración continua es una referencia útil si tu equipo todavía necesita una base de CI limpia y repetible.

Evitar la versión del generador evita una de las fallas más feas en las líneas de pipeline de codegen, la desviación de salida invisible. Si un desarrollador actualiza la versión del generador localmente y otro no, el archivo generado puede convertirse en una fuente de ruido aleatorio en lugar de señal. La CI debe hacer que eso sea imposible.

El resultado es una pipeline donde los cambios de esquema, la generación de tipos, las comprobaciones del compilador y las pruebas de contrato se refuerzan mutuamente. Eso es lo que hace que el flujo sea honesto.

Pipelines Mantenibles, Rendimiento y una Lista de Verificación Final

Una lista de verificación que muestra cuatro pasos clave para mantener una pipeline de OpenAPI TypeScript para proyectos de desarrollo de software.

Las pipelines que sobreviven son las que tienen una gobernanza aburrida. Versiona la especificación, revisa los cambios de esquema como code, fija la versión del generador y documenta cómo se aprueban los cambios que rompen la compatibilidad. Si el proceso es vago, las personas lo rodearán y entonces los tipos generados se convertirán en decoración en lugar de enfoque.

Unos pocos palancas de rendimiento realmente importan

La generación incremental ayuda en los monorepos donde la especificación cambia con frecuencia pero solo un paquete la consume. tsc --incremental Puede eliminar el trabajo repetitivo del compilador y desactivar las banderas de salida que no necesitas en los builds de producción para mantener la superficie generada más pequeña. En la práctica, el mayor beneficio sigue siendo social, no técnico, porque una pipeline predecible se ejecuta con más frecuencia que una inteligente.

La lista de verificación a continuación es la que vale la pena mantener cerca:

  • Pegar la versión: Bloquea la openapi-typescript versión en package.json de esta manera, el resultado no se desplaza entre máquinas.
  • Revisión de esquema: Trate los cambios en la especificación como cambios en el contrato revisable, no como mantenimiento.
  • Detección de desplazamiento: Regenera en CI y falla en la diferencia.
  • Validación de borde: Analiza payloads no confiables antes de que lleguen al estado de la aplicación o a la persistencia.
  • Pruebas de contrato: Ejecuta una comprobación respaldada por mock que demuestra que el consumidor code sigue siendo compatible con el esquema.
  • Política de cambios disruptivos: Anota quién aprueba los cambios en la forma y cómo se notifican a los clientes.

A un pipeline que incluye esas puertas no solo genera tipos, hace visible el contrato. Esa visibilidad es lo que impide a los equipos confiar en un archivo que solo parece seguro.

Si estás enviando aplicaciones Capacitor o Electron y quieres que tu pipeline de actualización se comporte con la misma disciplina, Capgo te da una forma práctica de mover arreglos de JavaScript, CSS, copia, configuración y recursos rápidamente sin tener que esperar a la revisión de la tienda de aplicaciones. Visita Capgo para ver cómo sus paquetes firmados, protección de rollback y controles de liberación se integran en un proceso de liberación que necesita velocidad sin perder el control.

Actualizaciones en vivo para aplicaciones Capacitor

Cuando un error en la capa web está activo, envíe la corrección a través de Capgo en lugar de esperar días a la aprobación de la tienda de aplicaciones. Los usuarios obtienen la actualización en segundo plano mientras los cambios nativos siguen en el camino de revisión normal.

Comience ahora

Últimas noticias de nuestro Blog

Capgo le da las mejores pistas que necesita para crear una aplicación móvil verdaderamente profesional.