Ogni solido esempio API TypeScript per Capacitor inizia sempre allo stesso modo: con un'interfaccia plugin tipizzata. Definisci esplicitamente metodi, opzioni e risultati Promise, così il tuo code web e il layer nativo condivideranno un unico contratto garantito da TypeScript.
Indice dei contenuti
- Crea un'interfaccia plugin Capacitor fortemente tipizzata
- Guida rapida al design API
- Segnali di adozione
- Vantaggi per i team Capacitor
- Analisi del Business Case
- Tipizza correttamente gli argomenti del Listener
- Definire i contratti di Update
- Proteggere i Channel e la compatibilità
- Registrare i Listener in sicurezza
- Scegliere il metodo di cleanup corretto
- Tipizzare input e output con precisione
- Organizzare Code per i cambiamenti
- Come tipizzare i risultati Native dinamici?
- Come evitare unhandled rejections nei Listener?
- Come proteggere gli update di Capgo?
Crea un'interfaccia plugin Capacitor fortemente tipizzata
L'interfaccia descrive la API che la tua code web vede. L'implementazione native sottostante deve rispettare quel contratto — e TypeScript controlla nomi dei metodi, parametri e valori di ritorno prima ancora che la tua app venga eseguita.
import { registerPlugin } from ‘@capacitor/core’;
export interface DeviceStatus {\nonline: boolean;\nbatteryLevel?: number;\n}
export interface DevicePlugin {\ngetStatus(): Promise}
export const Device = registerPlugin
In queste poche righe succede molto:
- Tipi di ritorno espliciti rendono ogni risultato prevedibile.
- Oggetti options tipizzati intercetta proprietà mancanti o errate a tempo di compilazione.
- Metodi basati su Promise modellano il lavoro nativo che termina in modo asincrono.
- Un generico
registerPluginchiamata è ciò che connette il web API al bridge nativo. - Interfacce documentano il contratto senza aggiungere un byte di code a runtime.
Ogni punto di chiamata riceve lo stesso trattamento:
const status = await Device.getStatus(); console.log(status.online);
await Device.setLabel({ label: ‘Production’ });
Scambia { label: 'Production' } per { name: 'Production' } e il compilatore lo segnala immediatamente. Meglio così che scoprire l'incompatibilità dopo un rilascio mobile.
L'interfaccia è anche il luogo in cui si modellano i valori opzionali e i casi di errore. Se un metodo nativo non può sempre restituire la carica della batteria, batteryLevel?: number indica a ogni chiamante di gestire undefined.
Il diagramma seguente mostra come i metodi tipizzati, le opzioni, i valori di ritorno, le definizioni del bridge e i controlli a tempo di compilazione si collegano all'interno di un Capacitor API.

L'idea centrale: le definizioni dei tipi fluiscono dall'interfaccia web verso la logica della piattaforma nativa, e i controlli a tempo di compilazione proteggono ogni punto di chiamata.
Riferimento rapido per il design di API
| Elemento | Scopo | Esempio |
|---|---|---|
| Firma del metodo | Definisce il comportamento chiamabile | getStatus() |
| Tipo delle opzioni | Controlla la forma dell'input | { label: string } |
| Risultato della Promise | Rappresenta un'operazione async | Promise<DeviceStatus> |
| Interfaccia del risultato | Definisce i dati restituiti | online: boolean |
Per un riferimento più approfondito, leggi la guida alla creazione di API in TypeScript. Due abitudini fondamentali: non includere segreti o credenziali di firma nel client code, e testa l'interfaccia su ogni implementazione della piattaforma prima di pubblicare.
I team mobile devono gestire contemporaneamente JavaScript, code nativo, permessi del dispositivo e servizi di piattaforma asincroni. Un contratto TypeScript robusto funziona come una checklist condivisa in ogni punto di contatto, rendendo esplicite le aspettative prima che qualsiasi code venga distribuito su un dispositivo iOS o Android.

Per un esempio concreto esempio concreto di API TypeScript, confronta un metodo che restituisce Promise<DeviceStatus> con uno che restituisce dati non tipizzati. La versione tipizzata comunica al tuo editor e a ogni reviewer esattamente quali campi esistono. La versione non tipizzata sposta il lavoro di debugging su log di runtime, test manuali e, nel peggiore dei casi, incidenti in produzione.
Segnali di Adozione
TypeScript ha superato di gran lunga la sua nicchia front-end. L'adozione è salita al 35% degli sviluppatori nel 2024, rispetto a solo il 12% nel 2017, and more than un milione di GitHub contributor lo indicheranno come linguaggio principale entro il 2025. Scopri tutti i risultati sull'adozione di TypeScript se vuoi i dati grezzi.
Questa traiettoria ha un impatto pratico sulle aziende mobile. Hiring, onboarding e la revisione di code ruotano sempre più attorno ai tipi condivisi. Chi si unisce a un progetto Capacitor può leggere un'interfaccia e capire il comportamento native previsto senza dover tracciare ogni singola implementazione.
Anche le API tipizzate rendono i rilasci più facili da gestire. Quando un metodo richiede un oggetto options specifico, una proprietà rinominata o un campo mancante fallisce al compile time, invece di generare silenziosamente una richiesta native incompleta.
Il strong typing anticipa i feedback critici, quando una correzione richiede minuti invece di un rilascio hotfix d'emergenza.
Vantaggi per i team Capacitor
Le app cross-platform solitamente espongono un API web-facing che gira sopra diverse implementazioni native. TypeScript non può garantire che ogni dettaglio native si comporti in modo identico, ma può mantenere le chiamate coerenti in tutta l'applicazione.
Applica tipi espliciti a:
- Input dei metodi, inclusi parametri obbligatori e opzionali
- Risultati delle Promise, così i dati di successo hanno sempre una forma prevedibile
- Eventi e listener, in modo che i callback gestiscano payload noti
- Errori e valori di stato, per mantenere visibili i percorsi di fallback
Questa struttura è fondamentale quando si integrano plugin nativi o servizi operativi. Aiuta inoltre i team che revisionano l'automazione degli update, dove un canale, un bundle identifier o un campo di compatibilità errato possono impattare un'ampia base di utenti.
Per approfondire i pattern correlati, leggi la nostra guida alla generazione di API tipizzate con OpenAPI. Spiega come le definizioni condivise riducano il drift manuale che solitamente si crea tra la documentazione API e il code dell'applicazione.
Analisi dei vantaggi
Il typing rigoroso richiede un investimento iniziale, specialmente se il vecchio code JavaScript ha strutture dati inconsistenti. Il ritorno si vede nel tempo: refactor più piccoli, maggiore chiarezza e molti meno problemi di integrazione.
Inizia dai confini che comportano più rischi:
- Definisci le interfacce di risposta per le chiamate native e remote.
- Tipizza gli oggetti options e i payload degli eventi.
- Attiva i controlli del compilatore in modalità strict gradualmente.
- Richiedi il type checking prima di pubblicare qualsiasi update.
Per i team mobile enterprise, questa base rende la manutenzione prevedibile su piattaforme, release e contributori.
Lo ScreenOrientationPlugin di Capacitor è un ottimo esempio di API TypeScript perché mappa alcuni semplici metodi web sul comportamento specifico del dispositivo. Il contratto pubblico rimane identico su tutte le piattaforme, mentre iOS e Android gestiscono i rispettivi dettagli nativi sottostanti.
import { registerPlugin } from ‘@capacitor/core’;
export type OrientationType =\n| ‘portrait-primary’\n| ‘portrait-secondary’\n| ‘landscape-primary’\n| ‘landscape-secondary’;
export interface OrientationData {\ntype: OrientationType;\nangle: number;\n}
export interface LockOptions {\norientation: OrientationType;\n}
export interface ScreenOrientationPlugin {\norientation(): Promise}
export const ScreenOrientation =\nregisterPlugin
Ecco un rapido riferimento per ogni firma:
orientation()— legge l'orientamento corrente in modo asincronolock()— accetta solo valori di orientamento notiunlock()— restituisce il controllo al normale comportamento del dispositivoaddListener()— emette un payload tipizzato a ogni cambio di orientamento
Poiché ogni metodo restituisce una Promise, puoi usare lo stesso pattern di chiamata sia con il bridge nativo sia con l'implementazione browser. Nessun branching, nessun caso speciale.
const current = await ScreenOrientation.orientation();
if (current.type.startsWith(‘landscape’)) {\nconsole.log("}Angle: ${current.angle});
}
await ScreenOrientation.lock({\norientation: ‘landscape-primary’,\n});
Digita un valore scritto male come landscape-main e la build fallisce all'istante. È un errore di compilazione che risolvi in pochi secondi, non un bug di runtime specifico della piattaforma da inseguire nei log del dispositivo.
Tipizza correttamente gli argomenti dei listener
I listener meritano lo stesso rigore dei metodi normali. Evita any qui, perché nasconde la differenza tra il payload di un evento e il risultato orientation() restituito.
const handleChange = (data: OrientationData) => {\ndocument.body.dataset.orientation = data.type;\n};
const subscription = await ScreenOrientation.addListener(\n‘screenOrientationChange’,\nhandleChange,\n);
await subscription.remove();
Condividi un singolo OrientationData tipo solo quando entrambe le implementazioni native garantiscono gli stessi campi. Se una piattaforma omette angle, rendilo opzionale e obbliga chi chiama la funzione a gestirlo undefined.
| Scelta di design | Pattern più sicuro |
|---|---|
| Input | Interfacce per opzioni nominate |
| Risultati | Tipi Promise espliciti |
| Eventi | Nomi degli eventi letterali |
| Cleanup | Restituzione di una subscription rimovibile |
L'interfaccia è il contratto di bridge, non l'implementazione nativa. Mantienila piccola, prevedibile e testabile.
Per il comportamento della piattaforma, i permessi e i passaggi di installazione, leggi la guida al plugin Capacitor Screen Orientation. Un'ultima abitudine da adottare: testa sia le chiamate valide che quelle rifiutate con impostazioni TypeScript rigorose. Questa combinazione permette di individuare nomi di metodi errati, campi mancanti e payload dei listener incompatibili molto prima di impacchettare la tua app mobile.
Capgo offre ai team Capacitor un modo per distribuire fix di JavaScript, CSS, configurazioni e asset senza attendere la revisione degli app store. Il segreto è trattare la sua pipeline di update come qualsiasi altro confine API tipizzato, così canali, regole di rollout, controlli di compatibilità e decisioni di rollback rimangono espliciti prima che un bundle raggiunga il dispositivo dell'utente.

Definire gli Update Contracts
Inizia definendo esattamente quali valori accetta la tua automazione. Le union letterali ti impediscono di deployare accidentalmente sul canale sbagliato, mentre le interfacce rendono auto-documentale la relazione tra un bundle e la sua versione native richiesta.
type Channel = ‘beta’ | ‘staging’ | ‘production’;
interface UpdateRequest {\nchannel: Channel;\nbundleVersion: string;\nminNativeVersion: string;\nrolloutPercent: number;\nsigned: boolean;\n}
interface UpdateResult {\naccepted: boolean;\nappliedOnNextLaunch: boolean;\nrollbackEnabled: boolean;\n}
Semplice e diretto esempio TypeScript API valida la richiesta prima di passarla al client Capgo:
async function publishUpdate(\nrequest: UpdateRequest,\n): Promise
return capgo.publish(request);\n}
Il nome esatto del metodo client cambia tra le versioni di Capgo SDK, quindi incapsulalo dietro la tua interfaccia. Questa astrazione ripaga ogni volta che fai un upgrade, evitando che i dettagli specifici del vendor si diffondano in tutto il codebase.
Proteggere i Channel e la compatibilità
Scegliere un channel non deve essere una scelta casuale. Un rilascio in produzione richiede controlli più rigorosi rispetto a un esperimento beta, specialmente quando il web bundle richiama capacità native non presenti nelle versioni precedenti dell'app.
function canDeploy( request: UpdateRequest, installedNativeVersion: string, ): boolean { return request.signed && installedNativeVersion >= request.minNativeVersion; }
Non confrontare le versioni come semplici stringhe. Usa una libreria di semantic-versioning dedicata così da 1.10.0 ordinati dopo 1.9.0. Prima di pubblicare su un channel, segui questa checklist:
- Conferma che il bundle sia firmato.
- Verifica che il channel di destinazione sia quello corretto.
- Confronta i range di compatibilità tra nativo e bundle.
- Pubblica prima a un pubblico limitato.
- Monitora i segnali di errore e tieni pronto un rollback.
Una pipeline di update tipizzata trasforma la policy di rilascio in code che i reviewer e la CI possono effettivamente ispezionare.
La consegna differenziale e i controlli dei canali di Capgo si integrano perfettamente in questo pattern, e la sua osservabilità a livello di device permette ai team di tracciare segnali di adozione o fallimento a posteriori. Per quanto riguarda l'instrumentation degli eventi, consulta questa guida al tracciamento degli eventi personalizzati con Capgo.
Le chiavi di firma e le credenziali admin devono stare sul server o sul sistema di CI, non nell'app distribuita. Applica l'update al prossimo avvio, testa il rollback con un bundle intenzionalmente rifiutato e logga ogni decisione con un risultato tipizzato. Questa combinazione garantisce una consegna rapida compatibile con un controllo disciplinato dei rilasci mobile.
I listener tipizzati sono ciò che rende le API asincrone affidabili. Che un callback tracci l'orientamento dello schermo o un evento di update di Capgo, dovrebbe ricevere la stessa struttura di payload su ogni piattaforma — e deve essere il compilatore a garantirlo.
interface UpdateEvent {\nversion: string;\nchannel: ‘beta’ | ‘production’;\navailable: boolean;\n}
type Listener
interface UpdateService {\naddListener(\nevent: ‘updateAvailable’,\ncallback: Listener
Questo Esempio API in TypeScript blocca il nome dell'evento a un letterale e lega il callback a un payload tipizzato. Il tuo editor offre l'autocompletamento version automaticamente, e il compilatore rifiuta qualsiasi callback che si aspetti dati non correlati. Richiede poco setup, ma ripaga ogni volta che cambia il API.
Vuoi vederlo in azione? Guarda il walkthrough:
Registrare i Listener in sicurezza
All'interno di un componente, conserva l'handle della subscription per rendere esplicita la cleanup. Lo stesso pattern si applica ai lifecycle hook di Angular, agli effect di React e ai mount hook di Vue senza modifiche.
let orientationHandle: { remove: () => Promise"}
async function start() { orientationHandle = await ScreenOrientation.addListener( ‘screenOrientationChange’, ({ type, angle }) => { console.log(type, angle); }, ); }
async function stop() {\nawait orientationHandle?.remove();\norientationHandle = undefined;\n}
Esegui la cleanup quando uno schermo scompare, non solo quando l'app si chiude. Se la salti, la navigazione lascerà i callback attaccati alle sorgenti degli eventi nativi. Ti ritroverai con task duplicati e aggiornamenti di stato obsoleti difficili da tracciare.
Ogni framework ti offre un hook per questo:
- Angular — attiva il cleanup da
ngOnDestroy - React — restituisci una funzione di cleanup async-safe da
useEffect - Vue — rimuovi la sottoscrizione in
onBeforeUnmount
Ogni
addListenerchiamata deve avere un percorso di rimozione corrispondente.
Scegli il metodo di cleanup corretto
Un handle restituito è la scelta giusta quando un componente gestisce una singola sottoscrizione. removeAllListeners() è l'ideale quando un servizio gestisce diversi listener e deve essere resettato completamente.
async function resetUpdates(service: UpdateService) {\nawait service.removeAllListeners();\n}
Non invocare il metodo globale da un componente condiviso se altre schermate dipendono ancora dal servizio. Se la gestione è locale, usa remove() handles.
| Situazione | Azione consigliata |
|---|---|
| Sottoscrizione singola del componente | Esegui handle.remove() |
| Chiusura del servizio | Esegui removeAllListeners() |
| Registrazione ripetuta | Inizializzazione della guard |
| Payload sconosciuto | Valida prima dell'uso |
Per le notifiche Capgo, tieni i payload degli update separati dagli eventi del dispositivo. Testa quindi registrazione, consegna e cleanup singolarmente — la Capgo custom event tracking guide approfondisce la parte di integrazione.
Prima del rilascio, verifica tre cose: l'unmounting rimuove effettivamente gli handler, le promise rifiutate vengono catturate e nessun callback può aggiornare un componente distrutto. Questa disciplina mantiene le app reattive Capacitor performanti su Angular, React e Vue.

Un esempio ben strutturato di Esempio API in TypeScript inizia con nomi che ne descrivano l'intento. Usa verbi per i metodi, sostantivi per le interfacce e mantieni suffissi coerenti come Options, Result, e Event. Nomi chiari riducono i tempi di onboarding perché gli sviluppatori comprendono il contratto senza dover aprire l'implementazione.
Mantieni le interfacce pubbliche snelle. Esponi le funzionalità tramite metodi mirati invece di accumulare operazioni slegate in un unico oggetto.
getStatus()legge lo stato.updateConfig(options)modifica la configurazione.addListener(event, callback)si iscrive ai cambiamenti.
Definisci Input e Output con precisione
Usa interfacce per le opzioni nominate se i parametri potrebbero aumentare:
interface PublishOptions {\nchannel: ‘beta’ | ‘production’;\nrolloutPercent: number;\n}
interface PublishResult {\nversion: string;\naccepted: boolean;\n}
async function publish(\noptions: PublishOptions,\n): Promise
I Generics sono fondamentali quando un API avvolge diversi payload ma deve preservarne i tipi specifici:
interface ApiResponse
async function request
Ma non aggiungere i generici solo per apparire flessibile. Un generico deve esprimere una relazione reale tra input e output; altrimenti, un'interfaccia concreta è più facile da leggere e mantenere.
Rendi difficili gli stati non validi, specialmente ai confini tra native, network e update.
Documenta il comportamento accanto al contratto. Copri permessi, unità, promise rifiutate, campi opzionali e se un metodo si applica subito o al prossimo avvio. I commenti inline dovrebbero spiegare le decisioni, non ripetere i nomi dei metodi.
Organizza Code per Change
Separa tipi, logica client, adapter di piattaforma e test in file prevedibili. Esporta i tipi pubblici da un unico entry point e mantieni privati i dettagli di implementazione.
| Interesse | Posizione consigliata |
|---|---|
| Interfacce pubbliche | types.ts |
| metodi API | client.ts |
| Adapter nativi | platform/ |
| Test di compatibilità | tests/ |
In caso di breaking change nei plugin, introduci una nuova interfaccia major o un layer di compatibilità, mantieni temporaneamente i metodi deprecated e documenta i passaggi per la migrazione. Scopri di più sulle strategie di versioning di API prima di modificare i consumer.
Esegui type check rigorosi e contract test in CI prima del rilascio. Per i workflow Capgo, verifica i valori dei channel, la compatibilità nativa, i bundle firmati e il comportamento di rollback come regole di rilascio tipizzate: questo permette di gestire gli update rapidi mentre team, piattaforme e integrazioni crescono.
Come tipizzare i risultati nativi dinamici?
Non lasciare che any i dati si propaghino nel tuo code quando un metodo nativo restituisce dati imprevedibili. Invece, definisci esplicitamente i campi su cui puoi contare, segna i valori realmente opzionali con ?, e sanifica gli input incerti al boundary prima che qualsiasi processo a valle li utilizzi.
interface NativeResult {\nsuccess: boolean;\nvalue?: string;\n}
async function readValue(): Promise
Questo approccio protegge chi effettua le chiamate, rendendo l'incertezza esplicita all'interno del tipo stesso. Per un'analisi più approfondita di questo pattern di interfaccia, rivedi la creazione di API in TypeScript.
Come possono i listener evitare unhandled rejections?
I callback asincroni devono essere difensivi per design. Gestisci i fallimenti all'interno del listener stesso, invece di sperare che il sistema di eventi ignori silenziosamente le promesse rifiutate.
const handleUpdate = (event: UpdateEvent): void => { void applyUpdate(event).catch((error: unknown) => { console.error(‘Update failed’, error); }); };
Mantieni il riferimento alla subscription e rimuovilo quando il componente viene smontato. Questo evita callback duplicate e aggiornamenti di stato obsoleti: la sezione sul ciclo di vita dei listener spiega tutto nel dettaglio.
Ogni listener asincrono richiede sia un percorso di errore che uno di cleanup.
Come posso proteggere gli aggiornamenti Capgo?
Le chiavi di firma e le credenziali amministrative devono restare sul tuo server o sul sistema di CI. Punto. Il client deve ricevere solo bundle firmati e usare risultati tipizzati per mostrare lo stato, mai per creare firme.
Prima del rilascio, configura canali separati, esegui controlli di compatibilità, imposta i limiti di rollout e pianifica la procedura di rollback. Capgo gestisce la consegna firmata, il controllo dei canali, il lancio dell'app al prossimo avvio e la protezione dai rollback per Capacitor ed Electron. La loro documentazione mostra come i workflow di rilascio tipizzati possano rendere più sicuro il tuo update pipeline.