Zum Hauptinhalt springen
Mobil Capacitor

TypeScript API Beispiel für Capacitor und Capgo

Entdecke ein praktisches TypeScript API Beispiel für Capacitor Plugins und Capgo Updates. Meistere typisierte Interfaces, Listener-Patterns und Implementierungsstrategien.

TypeScript API Beispiel für Capacitor und Capgo

Jedes solide TypeScript API Beispiel für Capacitor beginnt es auf die gleiche Weise: mit einer typisierten Plugin-Schnittstelle. Definiere deine Methoden, Optionen und Promise-Ergebnisse explizit, und dein Web-code sowie die native Ebene teilen sich einen einzigen Vertrag, den TypeScript tatsächlich durchsetzt.

Inhaltsverzeichnis

Stark typisiertes Capacitor-Plugin-Interface erstellen

Das Interface beschreibt die API, die dein Web-code sieht. Die native Implementierung dahinter muss diesen Vertrag einhalten – und TypeScript prüft Methodennamen, Parameter und Rückgabewerte, bevor deine App überhaupt läuft.

import { registerPlugin } from ‘@capacitor/core’;

export interface DeviceStatus { online: boolean; batteryLevel?: number; }

export interface DevicePlugin { getStatus(): Promise;\nsetLabel(options: { label: string }): Promise<{ saved: boolean }>;\n}

export const Device = registerPlugin(‘Device’);

In diesen wenigen Zeilen steckt viel:

  • Explizite Rückgabetypen machen jedes Ergebnis vorhersehbar.
  • Typisierte Optionsobjekte Fehlende oder falsch geschriebene Properties zur Compile-Zeit abfangen.
  • Promise-basierte Methoden modellieren native Arbeit, die asynchron abgeschlossen wird.
  • Ein generischer registerPlugin Aufruf ist das, was die Web-API mit der Native Bridge verbindet.
  • Schnittstellen dokumentieren den Contract, ohne ein Byte Runtime-code hinzuzufügen.

Jede Call Site wird gleich behandelt:

const status = await Device.getStatus(); console.log(status.online);

await Device.setLabel({ label: ‘Production’ });

Tauschen { label: 'Production' } für { name: 'Production' } und der Compiler markiert den Fehler sofort. Das schlägt es, die Abweichung erst nach einem mobilen Release zu entdecken.

Die Interface-Definition ist auch der Ort, an dem optionale Werte und Fehlerfälle modelliert werden. Wenn eine native Methode nicht immer einen Akkuwert liefern kann, batteryLevel?: number weist jeden Aufrufer an, mit undefined.

Die folgende Abbildung zeigt, wie typisierte Methoden, Optionen, Rückgabewerte, Bridge-Definitionen und Compile-Time-Checks innerhalb eines Capacitor API zusammenwirken.

Eine Abbildung, die die wichtigsten Vorteile einer stark typisierten TypeScript-Plugin-Schnittstelle für mobile Entwicklungsframeworks veranschaulicht.

Die Kernidee: Typdefinitionen fließen von der Web-Schnittstelle zur nativen Plattformlogik, und Compile-Time-Checks wachen an jeder Aufrufstelle.

Schnellreferenz für das API-Design

Element Zweck Beispiel
Methodensignatur Definiert aufrufbares Verhalten getStatus()
Options-Typ Steuert die Eingabestruktur { label: string }
Promise-Ergebnis Stellt asynchrone Arbeit dar Promise<DeviceStatus>
Result-Interface Definiert die zurückgegebenen Daten online: boolean

Für eine tiefere Referenz, lies den Guide zu APIs in TypeScript bauen. Zwei Gewohnheiten, die sich lohnen: Halte Secrets und Signing-Credentials aus dem Client code, und teste das Interface gegen jede Plattform-Implementierung, bevor du publishst.

Mobile Teams jonglieren gleichzeitig mit JavaScript, nativem code, Geräteberechtigungen und asynchronen Plattformservices. Ein starkes TypeScript-Vertrag funktioniert wie eine gemeinsame Checkliste an jeder dieser Grenzen und macht Erwartungen explizit, bevor code auf einem iOS- oder Android-Gerät landet.

A person coding on a laptop displaying code on a desk next to a coffee mug.

Für ein konkretes TypeScript API Beispiel, vergleiche eine Methode, die zurückgibt Promise<DeviceStatus> mit einer Hand untypisierte Daten zurück. Die typisierte Version sagt deinem Editor und jedem Reviewer genau, welche Felder existieren. Die untypisierte Version verlagert diese Erkennungsarbeit auf Runtime-Logs, manuelles Testing und im schlimmsten Fall auf Produktionsvorfälle.

Adoptionssignale

TypeScript hat seine Front-End-Nische längst verlassen. Die Adoption stieg auf 35 % der Entwickler im Jahr 2024, hoch von nur 12 % im Jahr 2017, und mehr als eine Million GitHub-Beitragende gelisteten es bis 2025 als ihre Primärsprache. Tauche in die vollständigen TypeScript-Adoptionsbefunde ein, wenn du die rohen Zahlen sehen möchtest.

Diese Entwicklung ist für Mobile-Organisationen praktisch relevant. Hiring, Onboarding und code-Review drehen sich zunehmend um geteilte Typen. Jemand, der ein Capacitor-Projekt beitreten, kann eine Interface lesen und das erwartete Native-Verhalten verstehen, ohne jede Implementierung nachverfolgen zu müssen.

Typisierte APIs erleichtern auch das Nachvollziehen von Release-Prozessen. Fordert eine Methode ein bestimmtes Options-Objekt, schlägt ein umbenanntes Property oder ein fehlendes Feld bereits zur Compile-Zeit fehl, statt stillschweigend eine unvollständige native Anfrage zu erzeugen.

Starkes Typing verlagert kritisches Feedback nach links, wenn ein Fix Minuten statt einer Notfall-Hotfix-Release dauert.

Vorteile für Capacitor-Teams

Cross-Platform-Apps exponieren typischerweise eine einzige webseitige API, die auf mehreren nativen Implementierungen aufsetzt. TypeScript kann nicht beweisen, dass jedes native Detail identisch funktioniert, aber es kann sicherstellen, dass deine Aufrufe über die gesamte Anwendung konsistent bleiben.

Verwende explizite Typen für:

  • Methoden-Inputs, inklusive erforderlicher und optionaler Optionen
  • Promise-Ergebnisse, damit Success-Daten immer eine vorhersehbare Struktur haben
  • Events und Listener, damit Callbacks bekannte Payloads verarbeiten
  • Fehler und Statuswerte, damit Fallback-Pfade sichtbar bleiben

Diese Struktur zahlt sich bei der Integration von Device-Plugins oder operativen Services aus. Sie hilft Teams zudem bei der Prüfung der Update-Automatisierung, bei der ein falscher Channel, Bundle-Identifier oder ein Kompatibilitätsfeld sich auf eine große Nutzerbasis auswirken kann.

Für einen tieferen Einblick in verwandte Patterns lies unseren Guide zur Generierung typisierter APIs mit OpenAPI. Es erklärt, wie gemeinsame Definitionen den manuellen Drift reduzieren, der normalerweise zwischen der API-Dokumentation und dem Anwendungs-code entsteht.

Den Business Case erstellen

Strenge Typisierung erfordert zunächst etwas Aufwand, besonders wenn ältere JavaScript-code inkonsistente Datenstrukturen enthalten. Der Nutzen zeigt sich mit der Zeit: kleinere Refactors, klarere Zuständigkeiten und deutlich weniger Integrationsschocks.

Beginnen Sie mit den Grenzen, die das größte Risiko bergen:

  1. Definieren Sie Response-Interfaces für native und Remote-Aufrufe.
  2. Typisieren Sie Ihre Options-Objekte und Event-Payloads.
  3. Aktivieren Sie strenge Compiler-Checks schrittweise.
  4. Erfordern Sie Typprüfungen, bevor Sie ein Update veröffentlichen.

Für Enterprise-Mobilteams sorgt dieses Fundament für vorhersehbare Wartung über Plattformen, Releases und Mitwirkende hinweg.

Das ScreenOrientationPlugin von Capacitor eignet sich hervorragend TypeScript API Beispiel da es eine Handvoll einfacher Web-Methoden auf plattformspezifisches Geräteverhalten abbildet. Der öffentliche Vertrag bleibt über alle Plattformen identisch, während iOS und Android jeweils ihre eigenen nativen Details im Hintergrund abwickeln.

import { registerPlugin } from ‘@capacitor/core’;

export type OrientationType = | ‘portrait-primary’ | ‘portrait-secondary’ | ‘landscape-primary’ | ‘landscape-secondary’;

export interface OrientationData { type: OrientationType; angle: number; }

export interface LockOptions { orientation: OrientationType; }

export interface ScreenOrientationPlugin { orientation(): Promise;\nlock(options: LockOptions): Promise;\nunlock(): Promise;\naddListener(\neventName: ‘screenOrientationChange’,\nlistenerFunc: (data: OrientationData) =&gt; void,\n): Promise&lt;{ remove: () =&gt; Promise }&gt;; }

export const ScreenOrientation = registerPlugin(‘ScreenOrientation’);

Hier ist die kurze Referenz für jede Signatur:

  • orientation() — liest die aktuelle Ausrichtung asynchron aus
  • lock() — akzeptiert nur einen bekannten Orientierungswert
  • unlock() — übergibt die Kontrolle wieder an das normale Geräteverhalten
  • addListener() — feuert bei jeder Orientierungsänderung einen typisierten Payload

Da jede Methode ein Promise zurückgibt, kannst du dasselbe Pattern sowohl mit der nativen Bridge als auch mit einer Browser-Implementierung nutzen. Kein Branching, keine Sonderfälle.

const current = await ScreenOrientation.orientation();

if (current.type.startsWith(‘landscape’)) {\nconsole.log("}Angle: ${current.angle}); }

await ScreenOrientation.lock({ orientation: 'landscape-primary', });

Gib einen falsch geschriebenen Wert ein wie landscape-main und der Build schlägt sofort fehl. Das ist ein Compile-Error, den du in Sekunden behebst – kein plattformspezifischer Runtime-Bug, den du durch Device-Logs jagen musst.

Listener-Argumente korrekt typisieren

Listener verdienen die gleiche Strenge wie reguläre Methoden. Vermeide any hier, da es den Unterschied zwischen einem Event-Payload und dem Ergebnis, das es orientation() zurück.

const handleChange = (data: OrientationData) => { document.body.dataset.orientation = data.type; };

const subscription = await ScreenOrientation.addListener( ‘screenOrientationChange’, handleChange, );

await subscription.remove();

Teile nur einen einzigen OrientationData Typ, wenn beide nativen Implementierungen dieselben Felder garantieren. Falls eine Plattform angle, als optional markieren und Aufrufer zur Behandlung undefined.

Design-Entscheidung Sichereres Pattern
Eingaben Benannte Options-Interfaces
Ergebnisse Explizite Promise-Typen
Events Literale Event-Namen
Aufräumen Eine entfernbare Subscription zurückgeben

Das Interface ist der Bridge-Contract, nicht die native Implementierung. Halte es klein, vorhersehbar und testbar.

Für Plattformverhalten, Berechtigungen und Installationsschritte lies die Capacitor Screen Orientation Plugin-Anleitung. Eine letzte Gewohnheit, die sich lohnt: Teste sowohl gültige als auch abgelehnte Aufrufe unter strengen TypeScript-Einstellungen. Diese Kombination fängt falsche Methodennamen, fehlende Felder und inkompatible Listener-Payloads ab, lange bevor du deine mobile App paketierst.

Capgo ermöglicht Capacitor Teams, JavaScript-, CSS-, Konfigurations- und Asset-Fixes zu pushen, ohne auf das App-Store-Review zu warten. Der Trick ist, die Update-Pipeline wie jede andere typisierte API Boundary zu behandeln, damit Channels, Rollout-Regeln, Kompatibilitätsprüfungen und Rollback-Entscheidungen explizit bleiben, bevor ein Bundle überhaupt auf dem Gerät eines Nutzers landet.

Eine Person hält ein Smartphone, das den Unterschied zwischen Hoch- und Querformat-Modi anzeigt.

Update-Contracts definieren

Beginnen Sie damit, genau festzulegen, welche Werte Ihre Automatisierung akzeptiert. Literal Unions verhindern versehentliche Deployments in den falschen Channel, und Interfaces machen die Beziehung zwischen einem Bundle und seiner erforderlichen nativen Version selbst erklärend.

type Channel = ‘beta’ | ‘staging’ | ‘production’;

interface UpdateRequest { channel: Channel; bundleVersion: string; minNativeVersion: string; rolloutPercent: number; signed: boolean; }

interface UpdateResult { accepted: boolean; appliedOnNextLaunch: boolean; rollbackEnabled: boolean; }

Eine unkomplizierte TypeScript API Beispiel validiert die Anfrage, bevor sie an den Capgo-Client übergeben wird:

async function publishUpdate( request: UpdateRequest, ): Promise { if (!request.signed || request.rolloutPercent &lt; 0 || request.rolloutPercent &gt; 100) { throw new Error('Unsafe update request'); }

return capgo.publish(request); }

Der exakte Client-Methodenname variiert zwischen Capgo- und SDK-Versionen, also kapsle ihn hinter deinem eigenen Interface. Diese Isolation zahlt sich bei jedem Upgrade aus und verhindert, dass anbieterspezifische Details in deine gesamte Codebase durchsickern.

Channels und Kompatibilität absichern

Die Wahl eines Channels sollte nicht beiläufig sein. Ein Production-Release verlangt strengere Checks als ein Beta-Experiment – besonders wenn das Web-Bundle native Funktionen aufruft, die in früheren App-Versionen noch nicht existierten.

function canDeploy( request: UpdateRequest, installedNativeVersion: string, ): boolean { return request.signed && installedNativeVersion >= request.minNativeVersion; }

Vergleiche Versionen nicht mit einfachen Strings. Nutze lieber eine richtige Semantic-Version-Library, damit 1.10.0 sortiert nach 1.9.0. Bevor irgendetwas in einen Channel gelangt, gehe diese Checkliste durch:

  1. Bestätige, dass das Bundle signiert ist.
  2. Prüfe, ob der Ziel-Channel der Absicht entspricht.
  3. Vergleiche die Kompatibilitätsbereiche von Native und Bundle.
  4. Veröffentliche zuerst für eine begrenzte Zielgruppe.
  5. Beobachte Fehlersignale und halte einen Rollback bereit.

Eine typisierte Update-Pipeline verwandelt Release-Policies in code, die Reviewer und CI tatsächlich prüfen können.

Die Differential Delivery und die Channel-Steuerung von Capgo passen gut in dieses Muster, und die Observability auf Geräteebene lässt Teams Adoption oder Fehlersignale im Nachhinein nachverfolgen. Für die Event-Instrumentierung siehe diesen Guide zum Custom Event Tracking mit Capgo.

Signing Keys und Admin-Credentials gehören auf den Server oder ins CI-System, nicht in die ausgelieferte App. Wende das Update beim nächsten Start an, teste den Rollback mit einem absichtlich abgelehnten Bundle und logge jede Entscheidung mit einem typisierten Ergebnis. Diese Kombination hält schnelle Auslieferung mit disziplinierter Mobile-Release-Kontrolle vereinbar.

Typisierte Listener sind der Grund, warum man asynchronen APIs leicht vertrauen kann. Ob ein Callback die Bildschirmorientierung oder ein Update-Event von Capgo verfolgt – die Payload-Struktur sollte auf jeder Plattform gleich sein, und der Compiler sollte das erzwingen.

interface UpdateEvent {\nversion: string;\nchannel: ‘beta’ | ‘production’;\navailable: boolean;\n}

type Listener = (payload: T) => void;

interface UpdateService {\naddListener(\nevent: ‘updateAvailable’,\ncallback: Listener, ): Promise<{ remove: () => Promise }>; removeAllListeners(): Promise; }

Dies TypeScript API Beispiel fixiert den Eventnamen an einen Literal und bindet den Callback an einen typisierten Payload. Ihr Editor autocomplettiert version kostenlos, und der Compiler lehnt jeden Callback ab, der unerwartete Daten erwartet. Es ist ein kleiner Setup-Aufwand, der sich jedes Mal auszahlt, wenn sich API ändert.

Möchtest du es lieber in Aktion sehen? Schau dir das Walkthrough an:

Listener sicher registrieren

Innerhalb eines Components das Subscription-Handle beibehalten, damit das Cleanup explizit bleibt. Dasselbe Muster lässt sich ohne Änderungen in Angular-Lifecycle-Hooks, React-Effects und Vue-Mount-Hooks einbauen.

let orientationHandle: { remove: () =&gt; Promise } | undefined;

async function start() { orientationHandle = await ScreenOrientation.addListener( ‘screenOrientationChange’, ({ type, angle }) =&gt; { console.log(type, angle); }, ); }

async function stop() { await orientationHandle?.remove(); orientationHandle = undefined; }

Führe Cleanup aus, wenn ein Screen verschwindet – nicht nur, wenn die gesamte App geschlossen wird. Lass das aus, bleiben Callbacks an native Event-Quellen angehängt. Das führt zu doppelter Arbeit und veralteten State-Updates, die schwer zu verfolgen sind.

Jedes Framework bietet dir einen Hook dafür:

  • Angular – löse Cleanup aus ngOnDestroy
  • React – gib eine async-sichere Cleanup-Funktion zurück aus useEffect
  • Vue – entferne die Subscription in onBeforeUnmount

Jeder addListener Der Aufruf sollte einen passenden Pfad zur Entfernung haben.

Die richtige Cleanup-Methode wählen

Ein zurückgegebener Handle ist die richtige Wahl, wenn eine Komponente eine Subscription besitzt. removeAllListeners() glänzt, wenn ein Service mehrere Listener hält und vollständig zurückgesetzt wird.

async function resetUpdates(service: UpdateService) { await service.removeAllListeners(); }

Rufe die breite Methode nicht aus einer geteilten Komponente auf, solange andere Screens noch vom Service abhängen. Wenn die Ownership lokal ist, bleib bei individuellen remove() Handles.

Situation Empfohlene Aktion
Eine Komponente, eine Subscription Rufe handle.remove()
Service-Shutdown Rufe removeAllListeners()
Wiederholte Registrierung Initialisierung absichern
Unbekannter Payload Vor der Nutzung validieren

Für Capgo Benachrichtigungen sollten Update-Payloads getrennt von Device-Events behandelt werden. So lassen sich Registrierung, Zustellung und Cleanup separat testen — der Capgo Guide für Custom Event Tracking bietet mehr Details zur Integration.

Prüfe vor dem Release drei Dinge: Entfernt das Unmounting die Handler wirklich? Werden rejected Promises abgefangen? Kann ein Callback eine zerstörte Komponente updaten? Diese Disziplin hält reaktive Capacitor Apps in Angular, React und Vue performant.

Ein professioneller Softwareentwickler arbeitet an code in einem Dual-Monitor-Setup mit Kopfhörern.

Ein sauber gebautes TypeScript API Beispiel beginnt mit aussagekräftigen Namen. Nutze Verben für Methoden, Substantive für Interfaces und bleibe bei konsistenten Suffixen wie Options, Result, und Event. Klare Namen verkürzen das Onboarding, da Entwickler den Contract verstehen, ohne die Implementierung öffnen zu müssen.

Halte öffentliche Interfaces klein. Exponiere Funktionen über fokussierte Methoden, anstatt lose zusammenhängende Operationen in einem einzigen Objekt zu sammeln.

  • getStatus() liest den State.
  • updateConfig(options) ändert die Konfiguration.
  • addListener(event, callback) abonniert Änderungen.

Inputs und Outputs präzise typisieren

Nutze benannte Options-Interfaces, wenn Parameter wachsen könnten:

interface PublishOptions {\nchannel: ‘beta’ | ‘production’;\nrolloutPercent: number;\n}

interface PublishResult {\nversion: string;\naccepted: boolean;\n}

async function publish(\noptions: PublishOptions,\n): Promise { return client.publish(options); }

Generics haben ihre Berechtigung, wenn ein API verschiedene Payloads umschließt, aber deren spezifische Typen erhalten muss:

interface ApiResponse { data: T; requestId: string; }

async function request(path: string): Promise&lt;ApiResponse&gt; { return fetchJson&lt;ApiResponse&gt;(path); }

Füge aber keine Generics hinzu, nur um flexibel zu wirken. Ein Generic sollte eine echte Beziehung zwischen Input und Output ausdrücken – andernfalls ist eine konkrete Interface leichter zu lesen und zu warten.

Mach es schwer, ungültige Zustände darzustellen, besonders an nativen, Netzwerk- und Update-Grenzen.

Dokumentiere das Verhalten direkt neben dem Vertrag. Decke Berechtigungen, Einheiten, abgelehnte Promises, optionale Felder ab und ob eine Methode sofort oder beim nächsten Start greift. Inline-Kommentare sollten Entscheidungen erklären, nicht Methodennamen wiederholen.

Code für Änderungen organisieren

Trenne Typen, Client-Logik, Plattform-Adapter und Tests in vorhersehbare Dateien. Exportiere öffentliche Typen aus einem einzigen Entry Point und halte Implementierungsdetails privat.

Aspekt Empfohlener Ort
Öffentliche Interfaces types.ts
API Methoden client.ts
Native Adapter platform/
Kompatibilitätstests tests/

Bei Breaking Changes in Plugins sollte man ein neues Major-Interface oder einen Compatibility Layer einführen, veraltete Methoden vorübergehend beibehalten und Migrationsschritte dokumentieren. Mehr über API Versioning-Strategien erfahren bevor Sie die Consumer ändern.

Führen Sie vor dem Release strikte Type-Checks und Contract-Tests in der CI aus. Überprüfen Sie bei Capgo Workflows Channel-Werte, native Kompatibilität, signierte Bundles und das Rollback-Verhalten als typisierte Release-Regeln — so behalten Sie auch bei wachsenden Teams, Plattformen und Integrationen die Kontrolle über schnelle Updates.

Wie sollte ich dynamische native Ergebnisse typisieren?

Lassen Sie nicht any in Ihr code durchsickern, wenn eine native Methode unvorhersehbare Daten zurückgibt. Definieren Sie stattdessen explizit die Felder, auf die Sie sich verlassen können, und markieren Sie wirklich optionale Werte mit ?, und bereinigen Sie unsichere Eingaben an der Grenze, bevor sie weiterverarbeitet werden.

interface NativeResult {\nsuccess: boolean;\nvalue?: string;\n}

async function readValue(): Promise {\nconst result = await NativePlugin.read();\nreturn {\nsuccess: Boolean(result.success),\nvalue: typeof result.value === ‘string’ ? result.value : undefined,\n};\n}

Dieser Ansatz schützt deine Caller und macht die Unsicherheit gleichzeitig explizit im Typ. Für einen breiteren Blick auf dieses Interface-Pattern schau nochmal hier: APIs in TypeScript bauen.

Wie können Listener unhandled Rejections vermeiden?

Asynchrone Callbacks müssen von Grund auf defensiv programmiert sein. Fange Fehler direkt im Listener ab, anstatt darauf zu vertrauen, dass das Event-System rejected Promises stillschweigend schluckt.

const handleUpdate = (event: UpdateEvent): void => { void applyUpdate(event).catch((error: unknown) => { console.error(‘Update failed’, error); }); };

Behalte die Subscription-Referenz und entferne sie, wenn die Komponente unmountet. Das verhindert doppelte Callbacks und veraltete State-Updates — der Abschnitt zum Listener-Lifecycle erklärt das im Detail.

Jeder asynchrone Listener braucht einen Error-Path und einen Cleanup-Path.

Wie schütze ich Capgo-Updates?

Signing-Keys und Admin-Credentials bleiben auf deinem Server oder CI-System. Punkt. Der Client sollte nur signierte Bundles erhalten und typisierte Ergebnisse nutzen, um den Status anzuzeigen — niemals, um Signaturen zu erstellen.

Bevor du veröffentlichst: Richte separate Channel-Unions ein, führe Kompatibilitätsprüfungen durch, konfiguriere Rollout-Limits und plane deinen Rollback-Pfad. Capgo verwaltet signierte Auslieferung, Kanalsteuerung, Anwendung beim nächsten Start und Rollback-Schutz für Capacitor- und Electron-Apps. Die Dokumentation zeigt, wie typisierte Release-Workflows Ihre Update-Pipeline straffen können.

Live-Updates für Capacitor-Apps

Wenn ein Bug im Web-Layer live ist, liefere den Fix über Capgo aus, statt Tage auf die App-Store-Freigabe zu warten. Nutzer bekommen das Update im Hintergrund, während native Änderungen im normalen Review-Prozess bleiben.

Neues aus unserem Blog

Capgo gibt dir die besten Insights, um eine wirklich professionelle Mobile App zu erstellen.