Chaque exemple d'API TypeScript pour Capacitor commence de la même manière : avec une interface de plugin typée. Définissez explicitement vos méthodes, vos options et les résultats Promise, afin que votre code web et la couche native partagent un contrat unique que TypeScript impose réellement.
Table of Contents
- Créer une interface de plugin Capacitor fortement typée
- Aide-mémoire pour le design API
- Signaux d'adoption
- Avantages pour les équipes Capacitor
- Démontrer la valeur métier
- Typer correctement les arguments du listener
- Définir des contrats de mise à jour
- Sécuriser les canaux et la compatibilité
- Enregistrer les listeners en toute sécurité
- Choisir la bonne méthode de nettoyage
- Typer précisément les entrées et sorties
- Organiser Code pour évoluer
- Comment typer les résultats natifs dynamiques ?
- Comment éviter les rejets non gérés dans les listeners ?
- Comment protéger les mises à jour Capgo ?
Créez une interface de plugin Capacitor fortement typée
L'interface décrit l’API que votre code web voit. L'implémentation native sous-jacente doit respecter ce contrat — et TypeScript vérifie les noms de méthodes, les paramètres et les valeurs de retour avant même l'exécution de votre app.
import { registerPlugin } from ‘@capacitor/core’;
export interface DeviceStatus {\nonline: boolean;\nbatteryLevel?: number;\n}
export interface DevicePlugin {\ngetStatus(): Promise}
export const Device = registerPlugin
Beaucoup de choses se passent dans ces quelques lignes :
- Types de retour explicites rendent chaque résultat prévisible.
- Objets d'options typés catch missing or misspelled properties at compile time.
- Méthodes basées sur les Promise modéliser le travail natif qui s'exécute de manière asynchrone.
- Un générique
registerPluginappel est ce qui connecte l’API web au bridge natif. - Interfaces documentent le contrat sans ajouter un seul octet de code au runtime.
Chaque point d'appel reçoit le même traitement :
const status = await Device.getStatus(); console.log(status.online);
await Device.setLabel({ label: ‘Production’ });
Remplacer { label: 'Production' } dans les { name: 'Production' } et le compilateur le signale immédiatement. Cela vaut mieux que de découvrir l'incohérence après une release mobile.
L'interface est aussi l'endroit où vous modélisez les valeurs optionnelles et les cas d'erreur. Si une méthode native ne peut pas toujours fournir une lecture de batterie, batteryLevel?: number indique à chaque appelant de gérer undefined.
Le diagramme ci-dessous montre comment les méthodes typées, les options, les valeurs de retour, les définitions de bridge et les vérifications à la compilation s'articulent au sein d'un Capacitor API.

L'idée centrale : les définitions de type circulent de l'interface web vers la logique de la plateforme native, et les vérifications à la compilation sécurisent chaque point d'appel.
Aperçu rapide du design API
| Élément | Finalité | Exemple |
|---|---|---|
| Signature de la méthode | Définit le comportement appelable | getStatus() |
| Type des options | Contrôle la structure de l'entrée | { label: string } |
| Résultat de la Promise | Représente un travail asynchrone | Promise<DeviceStatus> |
| Interface du résultat | Définit les données retournées | online: boolean |
Pour une référence plus approfondie, lisez le guide sur la création d'API en TypeScript. Deux habitudes à adopter : ne laissez pas de secrets ou d'identifiants de signature dans le code client, et testez l'interface par rapport à chaque implémentation de plateforme avant de publier.
Les équipes mobiles jonglent simultanément avec le JavaScript, le code natif, les permissions de l'appareil et les services de plateforme asynchrones. Un contrat TypeScript robuste agit comme une checklist partagée à chaque interface, rendant les attentes explicites avant qu'un code n'atterrisse sur un appareil iOS ou Android.

Pour un exemple concret exemple de API TypeScriptconcret, comparez une méthode qui retourne Promise<DeviceStatus> avec une autre qui renvoie des données non typées. La version typée indique à votre éditeur et à chaque relecteur exactement quels champs existent. La version non typée reporte ce travail de découverte sur les logs au runtime, les tests manuels et, au pire, sur des incidents en production.
Signaux d'adoption
TypeScript a largement dépassé sa niche front-end. Son adoption a grimpé à 35 % des développeurs en 2024, contre seulement 12 % en 2017, et plus d' un million de contributeurs GitHub l'ont citée comme langage principal d'ici 2025. Explorez les résultats complets de l' adoption de TypeScript si vous voulez les chiffres bruts.
Cette trajectoire a un impact concret pour les organisations mobiles. Le recrutement, l'onboarding et la revue de code s'articulent de plus en plus autour de types partagés. Un développeur rejoignant un projet Capacitor peut lire une interface et comprendre le comportement natif attendu sans avoir à tracer chaque implémentation.
Les API typées facilitent aussi la compréhension des releases. Lorsqu'une méthode exige un objet d'options spécifique, une propriété renommée ou un champ manquant échouera au temps de build plutôt que de générer silencieusement une requête native incomplète.
Le typage fort permet de détecter les erreurs plus tôt, quand un correctif prend quelques minutes au lieu d'une release de hotfix en urgence.
Avantages pour les équipes Capacitor
Les apps cross-platform exposent généralement un API web qui repose sur plusieurs implémentations natives. TypeScript ne peut pas prouver que chaque détail natif se comporte de manière identique, mais il permet de garder vos appels cohérents dans toute l'application.
Appliquez des types explicites aux :
- Entrées de méthode, incluant les options requises et optionnelles
- Résultats de Promise, pour que les données de succès aient toujours une structure prévisible
- Événements et listeners, pour que les callbacks gèrent des payloads connus
- Erreurs et valeurs de statut, pour que les chemins de repli restent visibles
Cette structure est payante lors de l'intégration de plugins device ou de services opérationnels. Elle aide aussi les équipes qui révisent l'automatisation des mises à jour, où un mauvais canal, un bundle identifier ou un champ de compatibilité peut impacter une large base d'utilisateurs.
Pour approfondir ces patterns, lisez notre guide sur la génération d'API typées avec OpenAPI. Il explique comment les définitions partagées réduisent le décalage manuel qui s'installe normalement entre la documentation API et le code de l'application.
Justifier l'investissement
Le typage strict demande un investissement initial, surtout quand l'ancien code JavaScript contient des structures de données incohérentes. Le retour sur investissement se voit avec le temps : des refactors plus simples, une meilleure gestion des responsabilités et beaucoup moins de surprises lors de l'intégration.
Commencez par les limites qui présentent le plus de risques :
- Définissez des interfaces de réponse pour les appels natifs et distants.
- Typez vos objets d'options et vos payloads d'événements.
- Activez progressivement les vérifications strictes du compilateur.
- Exigez des vérifications de type avant de publier une mise à jour.
Pour les équipes mobiles en entreprise, cette base rend la maintenance prévisible sur toutes les plateformes, releases et contributeurs.
Capacitor’s ScreenOrientationPlugin est un excellent Exemple de API TypeScript car il mappe quelques méthodes web simples sur le comportement spécifique de l'appareil selon la plateforme. Le contrat public reste identique sur toutes les plateformes, tandis qu'iOS et Android gèrent chacun leurs propres détails natifs en arrière-plan.
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
Voici un aide-mémoire pour chaque signature :
orientation()— lit l'orientation actuelle de manière asynchronelock()— n'accepte que des valeurs d'orientation connuesunlock()— redonne le contrôl’au comportement normal de l'appareiladdListener()— déclenche un payload typé à chaque changement d'orientation
Comme chaque méthode retourne une Promise, vous pouvez utiliser le même pattern d'appel pour le bridge natif et pour une implémentation navigateur. Pas de branchements, pas de cas particuliers.
const current = await ScreenOrientation.orientation();
if (current.type.startsWith(‘landscape’)) {\nconsole.log("}Angle: ${current.angle});
}
await ScreenOrientation.lock({ orientation: ‘landscape-primary’, });
Tapez une valeur mal orthographiée comme landscape-main et le build échoue instantanément. C'est une erreur de compilation que vous corrigez en quelques secondes — pas un bug runtime spécifique à une plateforme que vous devez traquer dans les logs de l'appareil.
Tapez correctement les arguments du Listener
Les Listeners méritent la même rigueur que les méthodes classiques. Évitez any ici, car cela masque la différence entre le payload d'un événement et le résultat orientation() renvoyé.
const handleChange = (data: OrientationData) => {\ndocument.body.dataset.orientation = data.type;\n};
const subscription = await ScreenOrientation.addListener(\n‘screenOrientationChange’,\nhandleChange,\n);
await subscription.remove();
Ne partagez qu'un seul OrientationData type lorsque les deux implémentations natives garantissent les mêmes champs. Si une plateforme omet angle, marquez-le comme optionnel et forcez les appelants à gérer undefined.
| Choix de conception | Pattern plus sûr |
|---|---|
| Entrées | Interfaces d'options nommées |
| Résultats | Types de Promise explicites |
| Événements | Noms d'événements littéraux |
| Nettoyage | Retourner un abonnement supprimable |
L'interface est le contrat de liaison, pas l'implémentation native. Gardez-la petite, prévisible et testable.
Pour le comportement de la plateforme, les permissions et les étapes d'installation, lisez le guide du plugin Capacitor Screen Orientation. Une dernière habitude à adopter : testez les appels valides et les appels rejetés avec des paramètres TypeScript stricts. Cette combinaison permet de détecter les noms de méthodes erronés, les champs manquants et les payloads de listener incompatibles bien avant de packager votre application mobile.
Capgo permet aux équipes de Capacitor de déployer des correctifs JavaScript, CSS, de configuration et d'assets sans subir la revue des stores. L'astuce consiste à traiter son pipeline de mise à jour comme n'importe quelle autre limite API typée, afin que les canaux, les règles de déploiement progressif, les vérifications de compatibilité et les décisions de rollback restent explicites avant qu'un bundle n'atteigne l'appareil d'un utilisateur.

Définir les contrats de mise à jour
Commencez par définir précisément les valeurs acceptées par votre automatisation. Les unions littérales vous empêchent de déployer par erreur sur le mauvais canal, et les interfaces rendent la relation entre un bundle et sa version native requise auto-documentée.
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 exemple simple Exemple TypeScript API valide la requête avant de la transmettre au client Capgo :
async function publishUpdate(\nrequest: UpdateRequest,\n): Promise
return capgo.publish(request);\n}
Le nom exact de la méthode client change entre les versions de Capgo SDK, alors encapsulez-la derrière votre propre interface. Cette isolation est payante à chaque mise à jour et empêche les détails spécifiques au fournisseur de se propager dans votre codebase.
Sécuriser les canaux et la compatibilité
Le choix d'un canal ne doit pas se faire au hasard. Une release en production exige des vérifications plus strictes qu'une expérimentation bêta, surtout quand le bundle JS appelle des capacités natives qui n'existaient pas dans les versions précédentes de l'app.
function canDeploy( request: UpdateRequest, installedNativeVersion: string, ): boolean { return request.signed && installedNativeVersion >= request.minNativeVersion; }
Ne comparez pas les versions avec de simples chaînes de caractères. Utilisez une bibliothèque de versionnage sémantique pour 1.10.0 trie après 1.9.0. Avant d'envoyer quoi que ce soit sur un canal, passez par une checklist :
- Confirmez que le bundle est signé.
- Vérifiez que le canal cible correspond à l'intention.
- Comparez les plages de compatibilité entre le natif et le bundle.
- Publiez d'abord auprès d'une audience limitée.
- Surveillez les signaux d'erreur et gardez un rollback prêt.
Un pipeline de mise à jour typé transforme la politique de release en code que les relecteurs et la CI peuvent réellement inspecter.
La livraison différentielle et les contrôles de canaux de Capgo s'intègrent parfaitement à ce modèle, et son observabilité au niveau de l'appareil permet aux équipes de retracer l'adoption ou les signaux d'échec après coup. Pour l'instrumentation des événements, consultez ce guide sur le suivi d'événements personnalisés avec Capgo.
Les clés de signature et les identifiants admin doivent rester sur le serveur ou le système de CI, pas dans l'app livrée. Appliquez la mise à jour au prochain lancement, testez le rollback avec un bundle intentionnellement rejeté, et loguez chaque décision avec un résultat typé. Cette combinaison permet de concilier livraison rapide et contrôle rigoureux des releases mobiles.
Ce sont les listeners typés qui rendent les API asynchrones dignes de confiance. Qu'un callback suive l'orientation de l'écran ou un événement de mise à jour Capgo, il doit recevoir la même structure de payload sur chaque plateforme — et c'est au compilateur de l'imposer.
interface UpdateEvent {\nversion: string;\nchannel: ‘beta’ | ‘production’;\navailable: boolean;\n}
type Listener
interface UpdateService {\naddListener(\nevent: ‘updateAvailable’,\ncallback: Listener"}
Ceci Exemple TypeScript API fixe le nom de l'événement à un littéral et associe le callback à un payload typé. Votre éditeur propose l'autocomplétion version gratuitement, et le compilateur rejette tout callback qui s'attend à des données sans rapport. C'est un peu de configuration, et ça vaut le coup à chaque fois que API change.
Vous préférez le voir en action ? Regardez le tutoriel :
Enregistrer les listeners en toute sécurité
À l'intérieur d'un composant, conservez la référence de l'abonnement pour que le nettoyage reste explicite. Ce même pattern s'adapte aux hooks de cycle de vie Angular, aux effets React et aux hooks de montage Vue sans modification.
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}
Exécutez le nettoyage lorsqu'un écran disparaît — pas seulement quand l'application entière se ferme. Si vous l'oubliez, la navigation laisse des callbacks attachés aux sources d'événements natifs. Vous vous retrouvez avec des tâches dupliquées et des mises à jour d'état obsolètes pénibles à tracer.
Chaque framework propose un hook pour cela :
- Angular — déclencher le nettoyage depuis
ngOnDestroy - React — retourner une fonction de nettoyage async-safe depuis
useEffect - Vue — supprimer l'abonnement dans
onBeforeUnmount
Chaque
addListenerl'appel doit avoir un chemin de suppression correspondant.
Choisir la bonne méthode de nettoyage
Un handle retourné est le bon choix quand un composant possède un seul abonnement. removeAllListeners() est idéale quand un service gère plusieurs écouteurs et est entièrement réinitialisé.
async function resetUpdates(service: UpdateService) {\nawait service.removeAllListeners();\n}
N'appelez pas la méthode globale depuis un composant partagé si d'autres écrans dépendent encore du service. Si la propriété est locale, privilégiez des remove() handles.
| Situation | Action recommandée |
|---|---|
| Abonnement par composant | Appelez handle.remove() |
| Arrêt du service | Appelez removeAllListeners() |
| Enregistrement répété | Initialisation de la garde |
| Payload inconnu | Valider avant usage |
Pour les notifications Capgo, séparez les payloads de mise à jour des événements de l'appareil. Testez ensuite l'enregistrement, la livraison et le nettoyage séparément — le Guide de suivi des événements personnalisés Capgo en dit plus côté intégration.
Avant de livrer, vérifiez trois points : le démontage supprime bien les handlers, les promesses rejetées sont capturées, et aucun callback ne peut mettre à jour un composant détruit. Cette discipline garde les apps Capacitor réactives avec Angular, React et Vue.

Un code bien structuré Exemple TypeScript API commence par des noms qui décrivent l'intention. Utilisez des verbes pour les méthodes, des noms pour les interfaces, et gardez des suffixes cohérents comme Options, Result, et Event. Des noms clairs réduisent le temps d'onboarding car les développeurs comprennent le contrat sans ouvrir l'implémentation.
Gardez les interfaces publiques légères. Exposez les capacités via des méthodes ciblées plutôt que d'entasser des opérations peu liées sur un seul objet.
getStatus()lit l'état.updateConfig(options)modifie la configuration.addListener(event, callback)s'abonne aux changements.
Typage précis des entrées et sorties
Utilisez des interfaces d'options nommées si les paramètres risquent d'évoluer :
interface PublishOptions {\ncanal: ‘beta’ | ‘production’;\nrolloutPercent: number;\n}
interface PublishResult {\nversion: string;\naccepted: boolean;\n}
async function publish(\noptions: PublishOptions,\n): Promise
Les génériques sont indispensables lorsqu'un API enveloppe différents payloads tout en devant préserver leurs types spécifiques :
interface ApiResponse
async function request
Mais n'ajoutez pas de génériques juste pour paraître flexible. Un générique doit exprimer une relation réelle entre l'entrée et la sortie — sinon, une interface concrète est plus facile à lire et à maintenir.
Rendez les états invalides difficiles à représenter, surtout aux limites du natif, du réseau et des mises à jour.
Documentez le comportement juste à côté du contrat. Couvrez les permissions, les unités, les promesses rejetées, les champs optionnels, et si une méthode s'applique immédiatement ou au prochain lancement. Les commentaires inline doivent expliquer les décisions, pas répéter le nom des méthodes.
Organiser Code pour Change
Séparez les types, la logique client, les adaptateurs de plateforme et les tests dans des fichiers prévisibles. Exportez les types publics depuis un point d'entrée unique et gardez les détails d'implémentation privés.
| Préoccupation | Emplacement recommandé |
|---|---|
| Interfaces publiques | types.ts |
| méthodes API | client.ts |
| Adaptateurs natifs | platform/ |
| Tests de compatibilité | tests/ |
Pour les changements de plugin majeurs, introduisez une nouvelle interface majeure ou une couche de compatibilité, conservez temporairement les méthodes dépréciées et documentez les étapes de migration. En savoir plus sur les stratégies de versioning API avant de modifier les consommateurs.
Exécutez des vérifications de types strictes et des tests de contrat en CI avant de déployer. Pour les workflows Capgo, vérifiez les valeurs des canaux, la compatibilité native, les bundles signés et le comportement de rollback en tant que règles de release typées — cela permet de maîtriser les mises à jour rapides à mesure que les équipes, les plateformes et les intégrations grandissent.
Comment typer les résultats natifs dynamiques ?
Ne laissez pas any fuiter dans votre code lorsqu'une méthode native renvoie des données imprévisibles. Au lieu de cela, définissez explicitement les champs sur lesquels vous pouvez compter, marquez les valeurs réellement optionnelles avec ?, et assainissez les entrées incertaines à la limite avant qu'elles ne soient traitées par le reste du système.
interface NativeResult {\nsuccess: boolean;\nvalue?: string;\n}
async function readValue(): Promise
Cette approche protège vos appelants tout en rendant l'incertitude explicite dans le type lui-même. Pour une vue d'ensemble de ce pattern d'interface, consultez la création d'API en TypeScript.
How Can Listeners Avoid Unhandled Rejections?
Les callbacks asynchrones doivent être défensifs par conception. Capturez les échecs à l'intérieur du listener lui-même plutôt que de faire confiance au système d'événements pour ignorer silencieusement les promesses rejetées.
const handleUpdate = (event: UpdateEvent): void => { void applyUpdate(event).catch((error: unknown) => { console.error(‘Update failed’, error); }); };
Conservez la référence de l'abonnement et supprimez-la lors du démontage du composant. Cela évite les doublons de callbacks et les mises à jour d'état obsolètes — la section sur le cycle de vie des listeners détaille ce point.
Chaque listener asynchrone nécessite à la fois un chemin d'erreur et un chemin de nettoyage.
Comment protéger les mises à jour Capgo ?
Les clés de signature et les identifiants administratifs restent sur votre serveur ou votre système CI. Point final. Le client ne doit recevoir que des bundles signés et utiliser des résultats typés pour afficher le statut — jamais pour créer des signatures.
Avant la publication, configurez des unions de canaux distinctes, lancez des tests de compatibilité, définissez les limites de déploiement progressif et planifiez votre stratégie de rollback. Capgo gère la livraison signée, le contrôle des canaux, le lancement de l'application au prochain démarrage et la protection contre le rollback pour Capacitor et les apps Electron. Leur doc montre comment des workflows de release typés peuvent sécuriser votre pipeline de mise à jour.