Saltare al contenuto principale

OpenAPI TypeScript: Genera Tipi, Clienti e Validazione

Impara come funziona la generazione di OpenAPI TypeScript da fine a fine. Genera tipi, collega client, valuta in esecuzione e invia in modo sicuro da CI.

Martin Donadieu

Martin Donadieu

Content Marketer

OpenAPI TypeScript: Genera Tipi, Clienti e Validazione

Solitamente puoi rilevare il momento in cui un API pipeline inizia a mentire alla squadra. Un schema cambia, gli tipi generati si aggiornano senza lamentarsi, il PR va verde, e poi qualcuno nel front end continua a leggere la vecchia forma di risposta perché il wrapper ha nascosto l'errore. Quello è il problema di OpenAPI TypeScript, non se un generatore può sparare fuori interfacce.

La domanda utile è più difficile. Qual è il contratto che desideri tra schema, trasporto e validazione, e quali parti dovrebbero fallire rapidamente in tempo di compilazione invece di filtrarsi in esecuzione? Una volta che hai impostato OpenAPI TypeScript As una scelta di pipeline, i compromessi diventano molto più chiari, e gli strumenti smettono di fingere di essere la soluzione completa.

Tavola dei contenuti

Perché i Tipi Generati Non Sono Lo Stesso di un Sicuro API

Un collega unisce un PR che aggiunge un campo di risposta facoltativo. Il file generato si aggiorna pulitamente, la diff sembra noiosa, e tutti continuano. Poi il front end continua a leggere una forma più vecchia attraverso un wrapper manuale che era 'temporaneamente' castato con as anye la produzione inizia a comportarsi come se il contratto non fosse mai cambiato.

È questo il tranello con i tipi generati. TypeScript può solo proteggere il code che consuma i tipi generatie solo se il layer di trasporto non cancella nuovamente il contratto. La parte OpenAPI ti dà uno schema, non una garanzia che ogni chiamante lo rispetti. La discussione intorno alla comprensione dei collegamenti API è utile qui perché sposta la conversazione da un singolo strumento verso come i sistemi si connettono.

Dove le fallite si nascondono

I punti di interruzione più comuni sono noiosi, non esotici. Il deriva dello schema si verifica quando lo spec OpenAPI e il servizio in esecuzione smettono di corrispondere. La copertura parziale si manifesta quando uno spec solo modella il percorso felice, mentre l'app dipende da casi d'uso non documentati. Le coperture a mano sono spesso dove i tipi si indeboliscono, specialmente quando qualcuno vuole “muoversi velocemente” e utilizza any o un cast di risposta rilassato.

Regola pratica: se la copertura può mentire, il generatore non può salvarti.

There c'è anche un divario di runtime. I tipi TypeScript scompaiono dopo la compilazione, quindi non possono rifiutare JSON malformato che arriva via cavo. La rete non si cura di cosa il tuo editor ha inferito, e questo è il motivo per cui un client generato è solo una layer in un pipeline più sicuro API.

La questione operativa più ampia è la sicurezza e la disciplina dei contratti, non solo la comodità del developer. Se desideri una visione strutturata di come API i contratti si inseriscono in un ciclo di vita dell'app più ampio, questo guida interna su API i standard di sicurezza per la conformità con le store di app è un utile compagno.

La forma matura di pensare a openapi typescript è questa. Ti dà un ponte schema-tipi rigoroso, che è eccellente, ma non valuta le richieste, non impone la forma del payload di runtime o non ferma un wrapper lento da sminuire tutto. Il generatore è il 20 percento facile. Il resto è progettazione del pipeline, e questo è dove le squadre guadagnano fiducia o accumulano una falsa fiducia.

Generazione di tipi TypeScript da un OpenAPI Spec

Screenshot da https://openapi-ts.dev

La configurazione più leggera utile è spesso quella che sopravvive al vero churn del repository. Mantieni lo spec OpenAPI nello stesso repository, genera un file di tipo commesso e rendi visibile il drift nel CI al posto di affidarti a qualcuno che ricordi un passo di refresh. Una riga come npx openapi-typescript ./openapi.yaml -o ./src/types/api.d.ts ti dà un file di output deterministico che i revisori possono esaminare come qualsiasi altra modifica di origine.

I flag che contano davvero

The flag di output è importante perché rende esplicito l'artefatto generato. -o è utile quando desideri che i tipi generati preservino l'intento readonly nell'output, e --immutable mantiene le differenze stabili quando cambia l'ordine dello schema senza significato semantico. --alphabetize è importante quando il tuo team preferisce gli enum nella superficie generata invece delle unioni. --enum Il progetto stesso documenta chiaramente lo scopo, è un

generatore di tipi , non un runtime del client o un layer di richiesta, e quella limitazione aiuta quando desideri un setup leggero, tipo-first.Il repository del progetto mostra anche il modello di manutenzione dietro lo strumento, che è parte di cosa rende gli strumenti open source sostenibili in produzione quando i documenti e le rilasci rimangono attivi, come discusso in il caso per la manutenzione open source. Una lettura pratica di quella posizione è il repository del progetto GitHub repository and CLI documentation.

e la documentazione di __CAPGO_KEEP_1__ package.json così il comando vive accanto agli altri script di costruzione, quindi eseguilo ogni volta che cambia la specifica. In CI, rigenera il file e falli se git diff mostra la deriva. Questo trasforma le modifiche ai contratti in lavoro di revisione visibile anziché rischio silenzioso di esecuzione.

L'aspetto del schema conta quanto l'aspetto della riga di comando. Il progetto consiglia compilerOptions.noUncheckedIndexedAccess così additionalProperties diventare T | undefined, che impone un'individuazione più sicura nei siti di chiamata. Consiglia anche di utilizzare oneOf da solo anziché mescolarlo con composizione extra, e di mantenere $defs alla radice quando la posizione è ambigua, perché le definizioni mal posizionate possono scomparire dal output generato. Un altro dettaglio salva tempo in seguito, openapi-typescript non produrrà mai any, quindi la mancanza di dettagli del schema viene resa visibile in anticipo anziché essere nascosta sotto tipi permissivi.

Tieni la specifica esplicita, o il generatore esporrà fedelmente l'ambiguità di nuovo.

Il workflow che resiste è semplice. Metti la specifica sotto controllo di versione, rigenera su costruzione, commetti il file generato e lascia che il controllore di tipo si lamenti prima che qualcuno unisca una disallineamento. Questo ti dà un confine di contratto stabile per il resto della pipeline.

Scelta tra tipi puri, clienti completi e senza codifica

Modello Tempo di costruzione File di output Peso del pacchetto Miglior adatto
Tipi puri con un wrapper sottile Velocità Pochi Bassi Le squadre che vogliono il controllo e una superficie di runtime piccola
CodeGen dei clienti completi Slower Molti Più alto Le squadre che desiderano un handoff rapido e operazioni generate automaticamente
Nessun costruttore di richieste di codegen Velocità Nessuna o minima Basso Applicazioni con un unico codice che preferiscono la logica di trasporto scritta a mano

In realtà, la scelta non è «quale strumento vince». È piuttosto quale forma di pipeline si adatta al tuo repository, alla tua squadra e a quanto cambiamento il API subisce. In un benchmark del 2025 intorno a una grande specifica OpenAPI di circa 75.000 linee, 2 MB, e circa 1.200 operazioni, openapi-typescript output generato in circa 1,5 secondi in media, rispetto a circa 8,0 secondi per @hey-api/openapi-ts, 5,5 secondi per Orval, e 18,1 secondi per Kubb, mentre produce anche un singolo file di output rispetto a 16 per hey-api, 2,719 per OrvalEcco i dettagli del benchmark 3,877 I tipi puri favoriscono il controllo Kubb (Una configurazione di tipi puri si abbina bene con uno strato di richiesta manuale perché puoi mantenere il runtime piccolo e la superficie __CAPGO_KEEP_0__ noiosa. Ciò conta nei front end sensibili al bundler e nelle app in cui un team possiede sia la specifica che il consumatore. Se hai bisogno di un ricordo che l'esperienza del developer non è solo zucchero di sintassi, il).

l'angolo dell'esperienza del developer

è più facile da giudicare quando il tuo client API è breve, ovvio e revisionabile. I client completi favoriscono la velocità di handoff is easier to judge when your client code is short, obvious, and reviewable.

tutti cercano di fare di più dei tipi. Ciò può essere utile quando si desidera generare insieme i metodi di richiesta, i modelli e la tubatura, specialmente in una grande handoff tra team backend e frontend. Il costo è ovvio nel benchmark sopra, più file generati, più superficie di runtime e più spazio per la frizione di costruzione a mano a mano che la specifica cresce.

openapi-generator, hey-api, OrvalNon ci sono generazioni di codice favoriscono i refactoring locali Kubb I costruttori di richieste tipizzati e

e

Typed request builders and fetch I wrapper funzionano bene quando un codice di base possiede entrambe le estremità della forma e le API modifiche sono coordinate strettamente. Il lato negativo è la disciplina di manutenzione. Più team e repository si trovano tra produttore e consumatore, più probabile è che una richiesta manuale si allontani a meno che non si impongano test di contratto aggressivamente.

Il punto di decisione fondamentale non è ideologico. Se il budget del pacchetto è stretto, i tipi puri sono attraenti. Se il tuo team vuole una scaffolding massima e può assorbire l'output, i clienti completi riducono il tempo di configurazione. Se vuoi parti mobili minimale e puoi mantenere il contratto vicino, i costruttori di richieste senza codifica possono essere il trade interno giusto.

Impostazione di un Client Thin Typed intorno a Fetch o Axios

Un diagramma che illustra il processo di un Wrapper di Client Typed utilizzando definizioni di TypeScript API generate per le richieste web.

Un wrapper sottile è dove il generatore si ferma e il tuo'applicazione code inizia. Il wrapper dovrebbe esporre una funzione per operazione, accettare parametri e oggetti di query tipizzati e inviare la chiamata a fetch o un'istanza iniettata axios senza cercare di essere troppo astuto. In molti setup di produzione, quel layer rimane intorno 30–60 linee perché i tipi generati già trasportano la maggior parte della forma.

Ecco il modello mentale che tiene.

  • I parametri di percorso rimangono tipizzati così /users/{id} non può essere chiamato senza un id.
  • Gli oggetti Query rimangono tipizzati così i filtri facoltativi non si trasformano in zuppa di stringhe.
  • I corpi di risposta rimangono tipizzati così il parsing di code può fidarsi della forma stretta che si aspetta.

Un wrapper come quello è intenzionalmente noioso. Non dovrebbe inventare ritentativi, trasformazioni o politiche di autenticazione se appartengono altrove. Dovrebbe spostare la richiesta da un'operazione tipizzata nel layer di trasporto e poi restituire il risultato tipizzato di nuovo verso l'alto.

Tieni il wrapper noioso e leggero di dipendenze, o ogni futura modifica del codice generato si ripercuoterà sulla tua app.

L'errore comune è patchare le disallineazioni con as any quando i tipi generati non si allineano con la firma del vecchio wrapper. Ciò compra un build verde e un'app fragile. Ciò nasconde anche la rottura del contratto che volevi che il generatore rivelasse.

Per le squadre che preferiscono Axios, il pattern è lo stesso, solo cambia l'implementazione del trasporto. Per le squadre che vogliono un code più semplice sul lato del browser fetch è spesso sufficiente. La parte importante è che la funzione di richiesta accetta il tipo di percorso generato e restituisce una risposta tipizzata, non un oggetto con forma lassa che viene massaggiato in seguito.

Se utilizzi bene questo punto di intercettazione, openapi typescript dà una pulita divisione del lavoro. Lo schema vive nella spec, il trasporto vive nel wrapper, e l'app vede operazioni tipizzate invece di richieste ad hoc code.

Aggiungere la validazione in runtime con zod, ajv o io-ts

Il tipo TypeScript scompare alla runtime, e la rete non si cura della fiducia dell'editor. È per questo che il modello sicuro non è 'generare tipi e sperare', è 'generare tipi, poi validare all'orlo dove i dati non affidabili entrano nell'app'. Lo schema generato rimane la fonte di verità, e le librerie di validazione come zod, ajve io-ts gestiscono i controlli di confine che i tipi di compilazione non possono.

Validare dove i dati entrano

Per le app React, l'orlo è di solito subito dopo che la richiesta si risolve e prima che il payload entra nello stato. Per i server, è prima che il payload venga scritto in un database o consegnato a una regola commerciale. La regola è semplice, tenere la validazione vicina all'orlo e non disperdere controlli manuali attraverso le funzionalità code.

Un zod la forma può riflettere la forma di risposta generata senza sostituirlo:

import { z } from "zod";

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

Quell'esempio valida i campi che lo schema ha segnalato come facoltativi, e mantiene il controllo di runtime allineato con ciò che il generatore ha prodotto. ajv è una scelta forte quando si desidera una validazione JSON Schema ad alta velocità sul server, mentre io-ts ancora si adatta a team che già vivono nel fp-ts stile di composizione.

L'errore più grande è la validazione troppo tardi. Se il payload attraversa l'applicazione prima, il sistema di tipi è già stato bypassato e il bug ha un posto dove nascondersi. Una breve guida su test di unità per JavaScript si abbina bene con questo mindset, perché sia i test di unità che la validazione dei confini funzionano meglio quando catturano le cattive assunzioni presto.

La stratificazione pulita è prevedibile. OpenAPI TypeScript genera il contratto, il validatore controlla il payload runtime, e la tua app code vede solo i dati che sono sopravvissuti a entrambe le fasi. È un confine molto migliore che affidarsi a un tipo statico per polizia una risposta non affidabile.

Collocare Generazione, Validazione e Test del Contratto in CI

Screenshot da https://github.com

Un flusso che resiste trasforma il contratto in una porta, non in una suggestione. Regenera i tipi, falli se c'è un cambiamento, esegui il tsc --noEmit, e esercita la API forma contro uno strumento di mock o di contratto prima della fusione. Se blocchi la versione del generatore in package.jsonDue a due ingegneri non possono produrre output diversi dallo stesso spec.

Una semplice forma di GitHub Actions

Un flusso di lavoro pratico assomiglia a questo:

  1. Estrarre lo spec dal repository o dalla fonte generata.
  2. Rigenerare i tipi.
  3. Fallire il lavoro se git diff mostra modifiche.
  4. Eseguire tsc --noEmit.
  5. Eseguire un test di contratto contro un server di mock come Prism o un controllo supportato da Spectral.

La differenza chiave tra i test di contratto e i test di snapshot è lo scopo. I snapshot spesso ti dicono che il file è stato modificato. I test di contratto ti dicono se la forma continua a comportarsi come lo spec dice che dovrebbe.

Un server di mock è particolarmente utile quando il lavoro di backend e frontend è separato da barriere di tempo o di team. Dà al consumatore code una superficie prevedibile API mentre controlla il contratto reale anziché un fixture hard-codificato. Il guida per la configurazione di integrazione continua è una utile risorsa se il tuo team ha ancora bisogno di una baseline CI pulita e ripetibile.

Pinning la versione del generatore evita uno dei fallimenti più fastidiosi nelle pipeline di generazione del codice, la disallineamento invisibile dell'output. Se un developer aggiorna localmente il generatore e un altro no, il file generato può diventare una fonte di rumore casuale anziché di segnale. La CI dovrebbe rendere impossibile ciò.

Il risultato è una pipeline in cui le modifiche allo schema, la generazione dei tipi, i controlli del compilatore e le prove dei contratti si rafforzano a vicenda. È questo che rende il workflow onesto.

Pipelines Mantenibili, Prestazioni e Checklist finale

Una checklist che mostra quattro passaggi chiave per mantenere una pipeline OpenAPI TypeScript per progetti di sviluppo software.

Il pipeline che sopravvive sono quelli con una governance noiosa. Versiona lo spec, revisiona le modifiche allo schema come code, fissa il generatore e documenta come si approvano le modifiche che rompono il processo. Se il processo è vago, le persone lo aggireranno e poi i tipi generati diventeranno decorazione anziché enforcement.

Un paio di leve di prestazioni che contano davvero

La generazione incrementale aiuta nei monorepos dove lo spec cambia spesso ma solo un pacchetto lo consuma. tsc --incremental può eliminare il lavoro ripetuto del compilatore e disabilitando le bandiere di output non necessarie nei build di produzione mantiene la superficie generata più piccola. In pratica, il più grande vantaggio è ancora sociale, non tecnico, perché una pipeline prevedibile viene eseguita più spesso di una astuta.

La checklist che segue è quella da tenere vicina:

  • Version pinning: Fissa la versione del generatore openapi-typescript versione in package.json così l'output non si sposta tra macchine.
  • Recensione dello schema: Trattare le modifiche di specifica come modifiche contrattuali revisionabili, non come manutenzione.
  • Detezione dello spostamento: Rigenerare in CI e fallire su diff.
  • Validazione di bordo: Analizzare i payload non affidabili prima che raggiungano lo stato dell'applicazione o la persistenza.
  • Test del contratto: Eseguire un controllo con un mock che dimostri che il consumatore code ancora corrisponde allo schema.
  • Politica delle modifiche dirottanti: Scrivere chi approva le modifiche di forma e come i clienti vengono informati.

A un pipeline che include queste porte non genera solo tipi, ma rende il contratto visibile. Questa visibilità è ciò che impedisce alle squadre di fidarsi di un file che sembra sicuro.

Se stai distribuendo applicazioni Capacitor o Electron e desideri che il tuo pipeline di aggiornamento si comporti con la stessa disciplina, Capgo ti offre un modo pratico per spostare modifiche JavaScript, CSS, copia, configurazione e asset velocemente senza dover attendere la revisione delle app store. Visitare Capgo per vedere come i pacchetti firmati, la protezione del rollback e i controlli di rilascio si integrano in un processo di rilascio che richiede velocità senza perdere il controllo.

Aggiornamenti in tempo reale per le app Capacitor

Quando un bug del layer web è attivo, invia la correzione attraverso Capgo invece di aspettare giorni per l'approvazione della store. Gli utenti ricevono l'aggiornamento in background mentre le modifiche native rimangono nel normale percorso di revisione.

Inizia subito

Ultimi articoli dal nostro Blog

Capgo ti offre le migliori informazioni che ti servono per creare un'app mobile veramente professionale.