Saltare al contenuto principale
Sviluppo Mobile

OpenAPI TypeScript: Genera Tipi, Clienti e Validazione

Impara come funziona la generazione di OpenAPI TypeScript da capo a piedi. Genera tipi, collega i clienti, valuta in esecuzione e invia in modo sicuro da CI.

Martin Donadieu

Martin Donadieu

Content Marketer

OpenAPI TypeScript: Genera Tipi, Clienti e Validazione

Puoi riconoscere il momento in cui un API pipeline inizia a ingannare la squadra. Un schema cambia, gli tipi generati vengono aggiornati senza lamentarsi, il PR va verde, e poi qualcuno nel front-end continua a leggere la vecchia forma della risposta perché il wrapper ha cancellato l'errore. Quello è il problema di OpenAPI TypeScript, non se un generatore può produrre interfacce.

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

Indice dei contenuti

Perché i tipi generati non sono gli stessi di un API sicuro

Un collega unisce un PR che aggiunge un campo di risposta facoltativo. Il file generato si aggiorna pulitamente, la diff sembra noiosa e tutti si muovono avanti. Poi la 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ò proteggere solo 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 delle API connessioni è utile qui perché sposta la conversazione da un singolo strumento verso come i sistemi si connettono.

Dove si nascondono le fallite

I punti di rottura più comuni sono noiosi, non esotici. Lo schema drift si verifica quando lo spec OpenAPI e il servizio dispiegato 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. I wrapper 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 il wrapper può mentire, il generatore non può salvarti.

Esiste 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 una pipeline più sicura 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 standard di sicurezza per la conformità degli store 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 maldestro che sottende tutto. Il generatore è il 20 percento facile. Il resto è progettazione della pipeline, e questo è dove le squadre guadagnano fiducia o accumulano false certezze.

Generazione dei tipi TypeScript da una spec OpenAPI

Screenshot da https://openapi-ts.dev

La configurazione più leggera utile è spesso quella che sopravvive al reale churn del repository. Mantieni la spec OpenAPI nel repository stesso, genera un file di tipo commesso e rendi visibile la deriva in 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 ispezionare come qualsiasi altro cambiamento di origine.

I flag che contano realmente

The -o è importante la flag di output perché rende esplicito l'artefatto generato. --immutable è utile quando si desidera che i tipi generati preservino l'intento readonly nell'output, e --alphabetize conserva le differenze stabili quando cambia l'ordine dello schema senza significato semantico. --enum è importante quando il tuo team preferisce gli enum nella superficie generata al posto delle unioni.

Il progetto ha una documentazione chiara sulla propria portata, si tratta di un generatore di tipie non di un runtime del client o di un layer di richiesta, e tale limite aiuta quando si desidera un setup leggero, di tipo prima. Suo repository mostra anche il modello di manutenzione dietro lo strumento, che è parte di perché il tooling open source può reggere in produzione quando i documenti e le rilasci rimangono attivi, come discusso inil caso per la manutenzione del tool open source GitHub repository and CLI documentation.

repository __CAPGO_KEEP_0__ e __CAPGO_KEEP_1__ documentazione package.json così il comando vive accanto agli altri script di costruzione, quindi eseguilo ogni volta che cambia lo spec. In CI, rigenera il file e falli se git diff mostra la deriva. Ciò trasforma le modifiche al contratto in lavoro di revisione visibile anziché rischio di esecuzione silenzioso.

Il lato dello schema conta quanto il lato della riga di comando. Il progetto raccomanda compilerOptions.noUncheckedIndexedAccess diventare additionalProperties che costringe un'indicizzazione più sicura nei siti di chiamata. Raccomanda inoltre di utilizzare T | undefinedda solo anziché mescolarlo con composizione extra, e di mantenere oneOf alla radice quando la posizione è ambigua, perché le definizioni mal posizionate possono scomparire dal output generato. Un altro dettaglio salva tempo in seguito $defs non produrrà openapi-typescript , quindi la mancanza di dettagli dello schema viene resa visibile in anticipo anziché essere nascosta sotto tipi permissivi. anyConserva lo spec esplicito, o il generatore esporrà la ambiguità di nuovo a te.

Il workflow che resiste è lineare. Metti lo spec sotto controllo di versione, rigenera a ogni costruzione, commetti il file generato e lascia che il controllore di tipo si lamenti prima che qualcuno unisca una disallineamento. Ciò ti dà un confine di contratto stabile per il resto della pipeline.

ciò significa

Scelta tra tipi puri, clienti completi e senza generazione di codice

Modello Tempo di costruzione File di output Peso del pacchetto Miglior adatto
Tipi puri con un wrapper sottile Veloci Pochi Bassi Le squadre che desiderano il controllo e una superficie di runtime piccola
Generazione di codice del client completo Più lento Molti Più alto Gli squadri che desiderano un handoff rapido e operazioni autogenerate
Nessun costruttore di richieste di codifica Veloci Nessuno o minimo Basso Solo applicazioni monorepo che preferiscono la logica di trasporto scritta a mano

La scelta non è davvero 'quali strumenti vincono'. È quale forma di pipeline si adatta al tuo repository, al tuo team 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 di 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 Orvale, e 3,877 per Kubb (dettagli di benchmark).

Tipi puri favoriscono il controllo

Una configurazione di tipi puri si abbina bene con uno strato di richiesta manuale perché puoi mantenere il runtime piccolo e la superficie API noiosa. Ciò conta nei front end sensibili al bundler e nelle app in cui un team possiede sia la spec sia il consumatore. Se hai bisogno di un ricordo che l'esperienza dello sviluppatore non è solo zucchero di sintassi, l' l'angolo dell'esperienza dello sviluppatore è più facile da giudicare quando il tuo client code è breve, ovvio e revisionabile.

Clienti completi favoriscono la velocità di passaggio

openapi-generator, hey-api, Orval, e Kubb tutti cercano di fare di più dei tipi. Ciò può essere utile quando desideri che i metodi di richiesta, i modelli e la tubatura vengano generati insieme, soprattutto in una grande passaggio di mano 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 build a mano che la spec cresce.

Senza codifica favorisce i refactor locali

Costruttori di richieste tipizzate e 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 layer di richiesta manuale si allontani a meno che non si impongano test di contratto con aggressività.

Il punto di decisione fondamentale non è ideologico. Se il budget del bundle è stretto, i tipi puri sono attraenti. Se il team vuole una scaffolding massima e può assorbire l'output, i clienti completi riducono il tempo di configurazione. Se si desidera minimizzare i componenti in movimento e si può mantenere il contratto vicino, i costruttori di richieste senza codifica possono essere la scelta giusta per un trade interno.

Impostare 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, quella 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 delle risposte rimangono tipizzati così la parsing di code può fidarsi della forma stretta che si aspetta.

Un wrapper come quello è intenzionalmente noioso. Non dovrebbe inventare ripetizioni, 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 verso l'alto.

Tieni il wrapper noioso e leggero di dipendenze, o ogni futuro cambiamento di codifica sarà riflesso nel tuo 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 desiderano una 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 sutura, openapi typescript viene fornito una netta divisione del lavoro. Lo schema vive nella spec, il trasporto vive nel wrapper, e l'app vede operazioni tipizzate al posto di richieste ad hoc code.

Aggiungere la validazione 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', ma '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, ajv, e 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 una database o consegnato a una regola commerciale. La regola è semplice, tenere la validazione vicina all'orlo e non disperdere controlli manuali attraverso le feature code.

A zod una 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 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 si adatta ancora a team che già vivono nel fp-ts lo 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 per nascondersi. Una breve guida sui 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 di runtime, e l'applicazione code vede solo i dati che sono sopravvissuti a entrambe le fasi. Quello è un confine molto migliore di fidarsi di un tipo statico per polizia una risposta non affidabile.

Mettere Generazione, Validazione e Test del Contratto in CI

Screenshot da https://github.com

Un flusso che dura trasforma il contratto in una porta, non in una suggestione. Regenera i tipi, falli se c'è un cambiamento, esegui tsc --noEmit, e esercita la API forma contro uno strumento di mock o di contratto prima di effettuare la fusione. Se blocchi la versione del generatore in package.jsonAi due ingegneri non possono produrre output diversi accidentalmente dalla stessa specifica.

Una semplice forma di azione GitHub

Un flusso di lavoro pratico assomiglia a questo:

  1. Estrarre la specifica 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 la specifica dice che dovrebbe.

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

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

Il risultato è una pipeline in cui le modifiche dello 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 un Elenco di Controllo finale

Un elenco 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 dello schema come code, blocca 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 invece di 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 che non serve nelle costruzioni 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.

L'elenco di controllo che segue è quello da tenere vicino:

  • Pinning della versione: Blocca il openapi-typescript versione in package.json così l'output non si allontana tra macchine.
  • Recensione dello schema: Trattare le modifiche allo spec come modifiche contrattuali da revisionare, non come manutenzione.
  • Detezione dello scostamento: 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 supportato da mock che dimostri che il consumatore code ancora corrisponde allo schema.
  • Politica di cambiamento di versione: Scrivere chi approva le modifiche di forma e come i clienti vengono informati.

A una pipeline che include queste porte non si limita a generare tipi, ma rende il contratto visibile. Questa visibilità è ciò che impedisce alle squadre di fidarsi di un file che sembra sicuro solo a prima vista.

Se si stanno distribuendo applicazioni Capacitor o Electron e si desidera che il proprio pipeline di aggiornamento si comporti con la stessa disciplina, Capgo offre una soluzione pratica per trasferire modifiche JavaScript, CSS, copia, configurazione e asset velocemente senza dover attendere la revisione delle app store. Visita Capgo Per vedere come i suoi 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 di layer web è attivo, invia la correzione attraverso Capgo invece di attendere giorni per l'approvazione della store. Gli utenti ricevono l'aggiornamento in background mentre le modifiche native rimangono nel normale percorso di revisione.

Sostegno umano da Martin

Inizia subito

Ultimi articoli del nostro Blog

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