Ogni plugin solido Esempio di API in TypeScript per Capacitor inizia allo stesso modo: con un'interfaccia plugin tipizzata. Definisci esplicitamente metodi, opzioni e i risultati delle Promise, così il tuo code web e il layer nativo condividono un unico contratto che TypeScript fa rispettare davvero.
Indice dei contenuti
- Crea un'interfaccia plugin Capacitor fortemente tipizzata
- Guida rapida al design di API
- Segnali di adozione
- Vantaggi per i team Capacitor
- Costruire il business case
- Tipizza correttamente gli argomenti del listener
- Definire i contratti di update
- Proteggere i canali e la compatibilità
- Registrare i listener in sicurezza
- Scegliere il giusto metodo di cleanup
- Tipizzare input e output con precisione
- Organizzare Code per i cambiamenti
- Come tipizzare i risultati nativi dinamici?
- Come possono i listener evitare le unhandled rejection?
- Come posso proteggere gli update di Capgo?
Crea un'interfaccia plugin Capacitor fortemente tipizzata
L'interfaccia descrive il API che il tuo code web vede. L'implementazione nativa dietro di essa deve rispettare quel contratto — e TypeScript verifica i nomi dei metodi, i parametri e i valori di ritorno prima che la tua app venga eseguita.
import { registerPlugin } from ‘@capacitor/core’;
export interface DeviceStatus { online: boolean; batteryLevel?: number; }
export interface DevicePlugin {
getStatus(): Promise
export const Device = registerPlugin
In quelle poche righe succede molto:
- Tipi di ritorno espliciti rendono ogni risultato prevedibile.
- Oggetti opzioni tipizzati rilevano proprietà mancanti o scritte male in fase di compilazione.
- Metodi basati su Promise modellano il lavoro nativo che termina in modo asincrono.
- Un generico
registerPluginchiamata è ciò che collega il web API al bridge nativo. - Interfacce documentare il contratto senza aggiungere un byte di runtime code.
Ogni punto di chiamata riceve lo stesso trattamento:
const status = await Device.getStatus(); console.log(status.online);
await Device.setLabel({ label: ‘Production’ });
Sostituisci { 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 una lettura 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.
Guida rapida al design di API
| Elemento | Scopo | Esempio |
|---|---|---|
| Firma del metodo | Definisce il comportamento chiamabile | getStatus() |
| Tipo Options | Controlla la forma dell'input | { label: string } |
| Risultato Promise | Rappresenta lavoro asincrono | Promise<DeviceStatus> |
| Interfaccia Result | Definisce i dati restituiti | online: boolean |
Per un riferimento più approfondito, leggi la guida su come creare API in TypeScript. Due abitudini da mantenere: escludi i segreti e le credenziali di firma dal client code, e testa l'interfaccia contro ogni implementazione di 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 a ciascuno di questi confini, rendendo esplicite le aspettative prima che qualsiasi code arrivi su un dispositivo iOS o Android.

Per un esempio Esempio di API in TypeScriptconcreto, confronta un metodo che restituisce Promise<DeviceStatus> con uno che restituisce dati non tipizzati. La versione tipizzata dice al tuo editor e a ogni reviewer esattamente quali campi esistono. Quella non tipizzata sposta il lavoro di scoperta 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 appena il 12% nel 2017, e molto altro un milione di GitHub contributor lo indicheranno come linguaggio principale entro il 2025. Scopri tutti i dati sull'adozione di TypeScript se vuoi vedere i numeri grezzi.
Questa tendenza ha un impatto concreto 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 nativo previsto senza dover tracciare ogni singola implementazione.
Le API tipizzate rendono anche più semplice ragionare sui rilasci. Quando un metodo richiede un oggetto options specifico, una proprietà rinominata o un campo mancante fallisce in fase di compilazione, invece di generare silenziosamente una richiesta nativa incompleta.
Il strong typing sposta a sinistra il feedback critico, quando una correzione richiede minuti invece di un rilascio hotfix d'emergenza.
Vantaggi per i team Capacitor
Le app cross-platform di solito espongono un API web-facing che si appoggia a diverse implementazioni native. TypeScript non può dimostrare che ogni dettaglio nativo si comporti allo stesso modo, ma può mantenere le chiamate coerenti in tutta l'applicazione.
Applica tipi espliciti a:
- Input dei metodi, incluse le opzioni obbligatorie e facoltative
- Risultati delle Promise, così i dati di successo hanno sempre una forma prevedibile
- Eventi e listener, così i callback gestiscono payload noti
- Errori e valori di stato, così i percorsi di fallback restano visibili
Questa struttura si rivela utile quando si integrano plugin di dispositivo o servizi operativi. Aiuta anche i team che revisionano l'automazione degli aggiornamenti, dove un canale, un bundle identifier o un campo di compatibilità errato può avere ripercussioni su un'ampia base di utenti.
Per un'analisi più approfondita dei 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 insinua tra la documentazione di API e il code dell'applicazione.
Costruire il business case
Il typing rigoroso richiede un investimento iniziale, soprattutto quando il vecchio code JavaScript ha strutture dati incoerenti. Il ritorno si vede nel tempo: refactoring più piccoli, ownership più chiara e molti meno imprevisti di integrazione.
Inizia dai confini che comportano il rischio maggiore:
- Definisci le interfacce di risposta per le chiamate native e remote.
- Tipizza i tuoi oggetti options e i payload degli eventi.
- Attiva i controlli rigorosi del compilatore in modo incrementale.
- Richiedi i controlli dei tipi 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 Esempio di API in TypeScript perché mappa alcuni semplici metodi web sul comportamento specifico del dispositivo. Il contratto pubblico rimane identico tra le piattaforme, mentre iOS e Android gestiscono i propri 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 {
orientation(): Promise}
export const ScreenOrientation =\nregisterPlugin
Ecco il riferimento rapido per ogni firma:
orientation()— legge l'orientamento attuale in modo asincronolock()— accetta solo un valore di orientamento notounlock()— restituisce il controllo al comportamento standard 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 errato 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 del listener
I listener meritano lo stesso rigore dei metodi normali. Evita any qui, perché nasconde la differenza tra un event payload e il risultato orientation() restituito.
const handleChange = (data: OrientationData) => { document.body.dataset.orientation = data.type; };
const subscription = await ScreenOrientation.addListener( ‘screenOrientationChange’, handleChange, );
await subscription.remove();
Condividi un singolo OrientationData type solo quando entrambe le implementazioni native garantiscono gli stessi campi. Se una piattaforma omette angle, rendilo opzionale e forza i chiamanti a gestire undefined.
| Scelta di design | Pattern più sicuro |
|---|---|
| Input | Interfacce di opzioni nominate |
| Risultati | Tipi Promise espliciti |
| Eventi | Nomi letterali degli eventi |
| Pulizia | Restituisci una subscription rimovibile |
L'interfaccia è il contratto del 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 che vale la pena adottare: testa sia le chiamate valide sia quelle rifiutate con TypeScript in modalità strict. Questa combinazione permette di individuare nomi di metodi errati, campi mancanti e payload dei listener incompatibili molto prima di creare il pacchetto della tua app mobile.
Capgo offre ai team Capacitor un modo per pushare fix di JavaScript, CSS, configurazioni e asset senza dover aspettare la revisione degli app store. La chiave è trattare la sua pipeline di update come qualsiasi altro confine tipizzato di API, così canali, regole di rollout, controlli di compatibilità e decisioni di rollback restano espliciti prima che un bundle raggiunga il dispositivo dell'utente.

Definire i contratti di update
Inizia definendo con precisione quali valori accetta la tua automazione. Le union di literal ti evitano di fare deploy per errore sul canale sbagliato, mentre le interfacce rendono autoesplicativo il rapporto tra un bundle e la versione nativa 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}
Un approccio semplice Esempio di API in TypeScript 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 separazione ripaga ad ogni upgrade e impedisce ai dettagli specifici del vendor di infiltrarsi nel tuo codebase.
Proteggere i canali e la compatibilità
La scelta del channel non deve essere casuale. Un rilascio in production richiede controlli più rigorosi rispetto a un esperimento beta, soprattutto quando il web bundle chiama capacità native che non esistevano nelle versioni precedenti dell'app.
function canDeploy( request: UpdateRequest, installedNativeVersion: string, ): boolean { return request.signed && installedNativeVersion >= request.minNativeVersion; }
Non confrontare le versioni con stringhe semplici. Usa una libreria di semantic-versioning appropriata in modo che 1.10.0 venga ordinata dopo 1.9.0. Prima che qualcosa raggiunga un channel, esegui questo checklist:
- Conferma che il bundle sia firmato.
- Verify the target channel matches intent.
- Confronta gli intervalli di compatibilità tra native e bundle.
- Pubblica prima per un pubblico limitato.
- Monitora i segnali di errore e tieni pronto il rollback.
Una pipeline di update tipizzata trasforma la policy di rilascio in code che reviewer e CI possono davvero ispezionare.
La distribuzione differenziale e i controlli sui channel di Capgo si inseriscono bene in questo pattern, e l'osservabilità a livello di device permette ai team di tracciare a posteriori segnali di adozione o di errore. Per la parte di 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 rifiutato di proposito e logga ogni decisione con un risultato tipizzato. Questa combinazione mantiene la distribuzione rapida compatibile con un controllo disciplinato dei rilasci mobile.
I listener tipizzati sono ciò che rende affidabili le API asincrone. Sia che un callback tracci l'orientamento dello schermo sia che riceva un evento di update di Capgo, deve ricevere la stessa struttura di payload su ogni piattaforma — e deve essere il compilatore a imporlo.
interface UpdateEvent {\nversion: string;\nchannel: ‘beta’ | ‘production’;\navailable: boolean;\n}
type Listener
interface UpdateService {\naddListener(\nevent: ‘updateAvailable’,\ncallback: Listener
Questo Esempio di API in TypeScript fissa il nome dell'evento su un letterale e lega il callback a un payload tipizzato. Il tuo editor completa automaticamente version gratuitamente, e il compilatore rifiuta qualsiasi callback che si aspetti dati non correlati. È una piccola configurazione, che ripaga ogni volta che API cambia.
Preferisci vederlo in azione? Guarda la demo:
Registrare i listener in sicurezza
All'interno di un componente, conserva il handle della subscription per mantenere la cleanup esplicita. Lo stesso pattern si integra nei lifecycle hook di Angular, negli effetti di React e nei 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() { await orientationHandle?.remove(); orientationHandle = undefined; }
Esegui la pulizia quando una schermata scompare, non solo quando l'intera app si chiude. Se la salti, la navigazione lascia i callback agganciati alle sorgenti di eventi native. Ti ritrovi con lavoro duplicato e aggiornamenti di stato obsoleti difficili da tracciare.
Ogni framework ti offre un hook per questo:
- Angular — avvia la cleanup da
ngOnDestroy - React — restituisci una funzione di cleanup async-safe da
useEffect - Vue — rimuovi la sottoscrizione in
onBeforeUnmount
Ogni
addListenercall should have a matching removal path.
Scegliere il giusto metodo di cleanup
Restituire un handle è la scelta giusta quando un componente gestisce una sola sottoscrizione. removeAllListeners() è l'ideale quando un servizio gestisce diversi listener e viene resettato completamente.
async function resetUpdates(service: UpdateService) {\nawait service.removeAllListeners();\n}
Non chiamare il metodo generico da un componente condiviso mentre altre schermate dipendono ancora dal servizio. Quando la gestione è locale, usa remove() gestisce.
| Situazione | Azione consigliata |
|---|---|
| Sottoscrizione singola del componente | Chiama handle.remove() |
| Chiusura del servizio | Chiama removeAllListeners() |
| Registrazione ripetuta | Inizializzazione della guard |
| Payload sconosciuto | Valida prima dell'uso |
Per le notifiche Capgo, mantieni i payload di aggiornamento separati dagli eventi del dispositivo. Poi testa registrazione, consegna e pulizia separatamente — il Capgo custom event tracking guide contiene maggiori dettagli sull'integrazione.
Prima di pubblicare, verifica tre cose: lo smontaggio rimuove davvero gli handler, le promise rifiutate vengono catturate e nessun callback può aggiornare un componente distrutto. Questa disciplina mantiene le app reattive Capacitor responsive su Angular, React e Vue.

Un'architettura solida Esempio di API in TypeScript inizia con nomi che descrivono l'intento. Usa verbi per i metodi, sostantivi per le interfacce e mantieni suffissi coerenti come Options, Result, e Event. Nomi chiari riducono il tempo di onboarding perché gli sviluppatori capiscono il contratto senza aprire l'implementazione.
Mantieni piccole le interfacce pubbliche. Espone le funzionalità tramite metodi mirati invece di ammassare operazioni poco correlate su un singolo oggetto.
getStatus()legge lo stato.updateConfig(options)modifica la configurazione.addListener(event, callback)si iscrive alle modifiche.
Tipizzare input e output con precisione
Usa interfacce di opzioni nominate quando i parametri potrebbero crescere:
interface PublishOptions { channel: ‘beta’ | ‘production’; rolloutPercent: number; }
interface PublishResult { version: string; accepted: boolean; }
async function publish(
options: PublishOptions,
): Promise
I generics hanno senso quando un API incapsula payload diversi 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 da rappresentare 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.
Organizzare Code per i cambiamenti
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.
| Aspetto | 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 tiene sotto controllo gli aggiornamenti rapidi mentre team, piattaforme e integrazioni crescono.
Come tipizzare i risultati nativi dinamici?
Non lasciare che any si propaghino nel tuo code quando un metodo nativo restituisce dati imprevedibili. Definisci invece esplicitamente i campi su cui puoi contare, segna i valori davvero opzionali con ?, e sanitizza gli input incerti al boundary prima che qualsiasi cosa a valle li tocchi.
interface NativeResult {\nsuccess: boolean;\nvalue?: string;\n}
async function readValue(): Promise
Questo approccio mantiene i chiamanti al sicuro rendendo l'incertezza esplicita nel tipo stesso. Per una panoramica più ampia di questo pattern di interfaccia, rivedi creare API in TypeScript.
Come possono i listener evitare le unhandled rejection?
I callback asincroni devono essere difensivi per design. Cattura i fallimenti all'interno del listener stesso, invece di fidarti del sistema di eventi che inghiotte silenziosamente le promise rifiutate.
const handleUpdate = (event: UpdateEvent): void => { void applyUpdate(event).catch((error: unknown) => { console.error('Update failed', error); }); };
Conserva il riferimento alla subscription e rimuovilo quando il componente viene smontato. Questo evita callback duplicati e aggiornamenti di stato obsoleti: la sezione sul ciclo di vita dei listener lo spiega in dettaglio.
Ogni listener asincrono richiede sia la gestione degli errori sia il cleanup.
Come posso proteggere gli update di Capgo?
Le chiavi di firma e le credenziali amministrative restano sul tuo server o sul sistema CI. Punto. Il client deve ricevere solo bundle firmati e usare risultati tipizzati per visualizzare lo stato — mai per creare firme.
Prima di pubblicare, configura union di canali separate, esegui controlli di compatibilità, imposta i limiti di rollout e pianifica il percorso di rollback. Capgo gestisce la consegna firmata, il controllo dei canali, l'applicazione al prossimo avvio e la protezione del rollback per app Capacitor ed Electron. La loro documentazione mostra come i workflow di release tipizzati possano rendere più solida la tua pipeline di update.