Setiap yang solid contoh API TypeScript untuk Capacitor dimulai dengan cara yang sama: dengan interface plugin yang bertipe. Tuliskan method, opsi, dan hasil Promise Anda secara eksplisit, sehingga web code dan native layer Anda berbagi satu kontrak yang benar-benar ditegakkan TypeScript.
Table of Contents
- Buat Interface Plugin Capacitor yang Strongly Typed
- Referensi Cepat untuk Desain API
- Sinyal Adopsi
- Keuntungan bagi Tim Capacitor
- Menyusun Business Case
- Beri Tipe Argumen Listener dengan Benar
- Definisikan Kontrak Update
- Lindungi Channel dan Kompatibilitas
- Daftarkan Listener dengan Aman
- Pilih Metode Cleanup yang Tepat
- Tentukan Tipe Input dan Output secara Presisi
- Atur Code untuk Perubahan
- Bagaimana Cara Menentukan Tipe Hasil Native Dinamis?
- Bagaimana Cara Listener Menghindari Unhandled Rejection?
- Bagaimana Cara Melindungi Update Capgo?
Buat Interface Plugin Capacitor yang Strongly Typed
Interface ini mendeskripsikan API yang dilihat oleh code web Anda. Implementasi native di baliknya harus mematuhi kontrak tersebut — dan TypeScript memeriksa nama method, parameter, serta nilai return sebelum aplikasi Anda dijalankan.
import { registerPlugin } from '@capacitor/core';
export interface DeviceStatus { online: boolean; batteryLevel?: number; }
export interface DevicePlugin {
getStatus(): Promise
export const Device = registerPlugin
Ada banyak hal yang terjadi dalam beberapa baris itu:
- Tipe return eksplisit menjaga setiap hasil tetap dapat diprediksi.
- Objek opsi bertipe tangkap properti yang hilang atau salah ketik saat compile time.
- Metode berbasis Promise memodelkan pekerjaan native yang selesai secara asinkron.
- Generic
registerPluginpanggilan adalah yang menghubungkan web API ke native bridge. - Interface mendokumentasikan kontrak tanpa menambah satu byte pun runtime code.
Setiap call site mendapatkan perlakuan yang sama:
const status = await Device.getStatus(); console.log(status.online);
await Device.setLabel({ label: ‘Production’ });
Tukar { label: 'Production' } untuk { name: 'Production' } dan compiler langsung menandai masalahnya di tempat. Itu lebih baik daripada menemukan ketidakcocokan setelah rilis mobile.
Interface juga tempat Anda memodelkan nilai opsional dan kasus kegagalan. Jika metode native tidak selalu bisa menghasilkan pembacaan baterai, batteryLevel?: number memberitahu setiap pemanggil untuk menangani undefined.
Diagram di bawah menunjukkan bagaimana metode bertipe, opsi, nilai return, definisi bridge, dan pemeriksaan compile-time terhubung di dalam Capacitor API.

Ide intinya: definisi tipe mengalir dari antarmuka web ke logika platform native, dan pemeriksaan compile-time menjaga setiap titik pemanggilan.
Referensi Cepat untuk Desain API
| Elemen | Tujuan | Contoh |
|---|---|---|
| Signature metode | Menentukan perilaku callable | getStatus() |
| Tipe opsi | Mengontrol bentuk input | { label: string } |
| Hasil Promise | Merepresentasikan proses async | Promise<DeviceStatus> |
| Interface hasil | Menentukan data yang dikembalikan | online: boolean |
Untuk referensi lebih dalam, baca panduan membangun API di TypeScript. Dua kebiasaan yang perlu dijaga: jangan sertakan secret dan kredensial signing di client code, dan uji interface terhadap implementasi tiap platform sebelum publish.
Tim mobile mengelola JavaScript, native code, izin perangkat, dan layanan platform asinkron sekaligus. Sebuah kontrak TypeScript yang kuat berfungsi seperti checklist bersama di setiap batas tersebut, membuat ekspektasi eksplisit sebelum code apa pun sampai ke perangkat iOS atau Android.

Untuk sebuah contoh API TypeScriptyang konkret, bandingkan metode yang mengembalikan Promise<DeviceStatus> dengan yang mengembalikan data untyped. Versi bertipe memberi tahu editor dan setiap reviewer persis field mana yang ada. Versi untyped membebankan pekerjaan penemuan itu ke runtime logs, testing manual, dan, paling buruk, insiden produksi.
Sinyal Adopsi
TypeScript telah berkembang jauh melampaui niche front-end. Adopsinya melonjak hingga 35% developer di tahun 2024, naik dari hanya 12% pada 2017, dan lebih dari satu juta kontributor GitHub menjadikannya sebagai bahasa utama mereka pada tahun 2025. Telusuri lebih lanjut temuan adopsi TypeScript jika Anda ingin angka mentahnya.
Tren itu penting bagi organisasi mobile secara praktis. Perekrutan, onboarding, dan code review semakin berpusat pada tipe bersama. Seseorang yang bergabung ke proyek Capacitor dapat membaca interface dan memahami perilaku native yang diharapkan tanpa harus menelusuri seluruh implementasi.
API bertipe juga membuat proses rilis lebih mudah dipahami. Ketika sebuah metode membutuhkan objek opsi tertentu, properti yang diganti nama atau field yang hilang akan gagal saat compile, bukan menghasilkan request native yang setengah jadi secara diam-diam.
Typing yang kuat menggeser umpan balik penting ke kiri, ketika perbaikan hanya butuh beberapa menit alih-alih rilis hotfix darurat.
Keuntungan bagi Tim Capacitor
Aplikasi lintas platform biasanya mengekspos satu API yang berhadapan dengan web, yang berada di atas beberapa implementasi native. TypeScript tidak bisa membuktikan bahwa setiap detail native berperilaku identik, tetapi bisa menjaga panggilan Anda tetap konsisten di seluruh aplikasi.
Terapkan tipe eksplisit pada:
- Input dari method, termasuk opsi wajib dan opsional
- Hasil Promise, agar data sukses selalu punya struktur yang bisa diprediksi
- Event dan listener, agar callback menangani payload yang sudah diketahui
- Error dan nilai status, agar jalur fallback tetap terlihat
Struktur tersebut sangat berguna saat mengintegrasikan plugin perangkat atau layanan operasional. Ini juga membantu tim saat meninjau otomatisasi update, di mana kesalahan channel, bundle identifier, atau field kompatibilitas dapat berdampak besar pada basis pengguna.
Untuk pembahasan lebih dalam mengenai pola terkait, baca panduan kami untuk membuat API bertipe dengan OpenAPI. Ini membahas bagaimana definisi bersama mengurangi pergeseran manual yang biasanya muncul antara dokumentasi API dan code aplikasi.
Menyusun Business Case
Strict typing memang butuh investasi di awal, terutama saat code JavaScript lama punya bentuk data yang tidak konsisten. Imbalannya terasa seiring waktu: refactor lebih kecil, ownership lebih jelas, dan jauh lebih sedikit kejutan integrasi.
Mulai dari batasan yang membawa risiko paling besar:
- Definisikan interface response untuk panggilan native dan remote.
- Beri tipe pada object options dan payload event Anda.
- Aktifkan strict compiler checks secara bertahap.
- Wajibkan type check sebelum publish update apa pun.
Bagi tim mobile enterprise, fondasi itu menjaga maintenance tetap bisa diprediksi lintas platform, rilis, dan kontributor.
ScreenOrientationPlugin milik Capacitor jadi contoh yang bagus contoh API TypeScript karena ia memetakan beberapa metode web sederhana ke perilaku perangkat yang spesifik platform. Kontrak publiknya tetap identik di semua platform, sementara iOS dan Android masing-masing menangani detail native masing-masing di balik layar.
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
Berikut referensi cepat untuk setiap signature:
orientation()— membaca orientasi saat ini secara asinkronlock()— hanya menerima nilai orientasi yang dikenalunlock()— mengembalikan kendali ke perilaku perangkat normaladdListener()— memicu payload bertipe setiap kali orientasi berubah
Karena setiap method mengembalikan Promise, Anda dapat menggunakan pola pemanggilan yang sama untuk native bridge maupun implementasi browser. Tanpa percabangan, tanpa kasus khusus.
const current = await ScreenOrientation.orientation();
if (current.type.startsWith(‘landscape’)) {
console.log(Angle: ${current.angle});
}
await ScreenOrientation.lock({ orientation: ‘landscape-primary’, });
Ketik nilai yang salah eja seperti landscape-main dan build langsung gagal. Itu adalah compile error yang bisa diperbaiki dalam hitungan detik — bukan bug runtime spesifik platform yang harus Anda telusuri lewat logs perangkat.
Beri Tipe Argumen Listener dengan Benar
Listeners juga butuh ketelitian yang sama seperti method biasa. Hindari any di sini, karena ini menyembunyikan perbedaan antara payload event dan hasil orientation() dikembalikan.
const handleChange = (data: OrientationData) => {\ndocument.body.dataset.orientation = data.type;\n};
const subscription = await ScreenOrientation.addListener(\n‘screenOrientationChange’,\nhandleChange,\n);
await subscription.remove();
Hanya gunakan satu OrientationData type saat kedua implementasi native menjamin field yang sama. Jika satu platform tidak menyertakan angle, tandai sebagai opsional dan paksa pemanggil untuk menangani undefined.
| Pilihan desain | Pola yang lebih aman |
|---|---|
| Input | Interface opsi bernama |
| Hasil | Tipe Promise eksplisit |
| Event | Nama event literal |
| Pembersihan | Kembalikan subscription yang bisa dihapus |
Interface adalah kontrak bridge, bukan implementasi native. Jaga agar tetap kecil, predictable, dan mudah diuji.
Untuk perilaku platform, izin, dan langkah instalasi, baca panduan plugin Capacitor Screen Orientation. Satu kebiasaan terakhir yang patut dicoba: uji panggilan yang valid maupun yang rejected dengan pengaturan TypeScript yang ketat. Kombinasi ini mendeteksi nama method yang salah, field yang hilang, dan payload listener yang tidak kompatibel jauh sebelum Anda mem-build aplikasi mobile.
Capgo memberi tim Capacitor cara untuk push perbaikan JavaScript, CSS, konfigurasi, dan asset tanpa harus menunggu review app store. Kuncinya adalah memperlakukan pipeline update-nya seperti boundary API bertipe lainnya, sehingga channel, aturan rollout, pengecekan kompatibilitas, dan keputusan rollback tetap eksplisit sebelum bundle sampai ke perangkat pengguna.

Definisikan Kontrak Update
Mulailah dengan menentukan nilai apa saja yang diterima otomatisasi Anda. Literal unions mencegah Anda tidak sengaja deploy ke channel yang keliru, dan interface membuat hubungan antara bundle dan versi native yang dibutuhkan terdokumentasi dengan sendirinya.
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}
Cara sederhana contoh API TypeScript memvalidasi request sebelum diteruskan ke client Capgo:
async function publishUpdate(\nrequest: UpdateRequest,\n): Promise
return capgo.publish(request);\n}
Nama metode klien yang tepat bisa berubah di antara versi Capgo SDK, jadi bungkus di balik interface Anda sendiri. Isolasi ini terasa manfaatnya setiap kali Anda upgrade dan mencegah detail spesifik vendor bocor ke seluruh codebase.
Lindungi Channel dan Kompatibilitas
Memilih channel tidak boleh sembarangan. Rilis produksi menuntut pemeriksaan yang lebih ketat daripada eksperimen beta, terutama saat web bundle memanggil kemampuan native yang belum ada di versi app sebelumnya.
function canDeploy( request: UpdateRequest, installedNativeVersion: string, ): boolean { return request.signed && installedNativeVersion >= request.minNativeVersion; }
Jangan bandingkan versi dengan string biasa. Gunakan library semantic-version yang tepat agar 1.10.0 diurutkan setelah 1.9.0. Sebelum apa pun masuk ke channel, jalankan checklist berikut:
- Pastikan bundle sudah ditandatangani.
- Verifikasi bahwa channel target sesuai dengan tujuan.
- Bandingkan rentang kompatibilitas native dan bundle.
- Publikasikan ke audiens terbatas terlebih dahulu.
- Pantau sinyal kegagalan dan siapkan rollback.
Pipeline update bertipe mengubah kebijakan rilis menjadi code yang benar-benar dapat diperiksa oleh reviewer dan CI.
Differential delivery dan kontrol channel dari Capgo cocok dengan pola tersebut, dan observability tingkat perangkatnya memungkinkan tim menelusuri sinyal adopsi atau kegagalan setelahnya. Untuk sisi instrumentasi event, lihat panduan ini tentang pelacakan event kustom dengan Capgo.
Signing keys dan kredensial admin harus disimpan di server atau sistem CI, bukan di dalam aplikasi yang dikirimkan. Terapkan update saat peluncuran berikutnya, uji rollback dengan bundle yang sengaja ditolak, dan catat setiap keputusan dengan hasil bertipe. Kombinasi ini menjaga pengiriman cepat tetap kompatibel dengan kontrol rilis mobile yang disiplin.
Listener bertipe adalah yang membuat API asinkron mudah dipercaya. Baik callback melacak orientasi layar maupun event update Capgo, ia harus menerima bentuk payload yang sama di setiap platform — dan compiler-lah yang harus menegakkannya.
interface UpdateEvent { version: string; channel: ‘beta’ | ‘production’; available: boolean; }
type Listener
interface UpdateService {
addListener(
event: ‘updateAvailable’,
callback: Listener
Ini contoh API TypeScript mengunci nama event ke literal dan mengikat callback ke payload bertipe. Editor Anda memberi autocomplete version secara gratis, dan compiler menolak callback yang mengharapkan data yang tidak terkait. Setup-nya sedikit, tapi hasilnya terasa setiap kali API berubah.
Mau lihat langsung cara kerjanya? Tonton walkthrough-nya:
Daftarkan Listener dengan Aman
Di dalam komponen, simpan subscription handle agar cleanup tetap eksplisit. Pola yang sama bisa langsung dipakai di lifecycle hook Angular, React effect, dan Vue mount hook tanpa perubahan.
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}
Jalankan cleanup saat layar menghilang — bukan hanya saat seluruh aplikasi ditutup. Kalau dilewati, navigasi akan meninggalkan callback yang tetap menempel di native event source. Akibatnya muncul pekerjaan ganda dan update state basi yang sulit dilacak.
Setiap framework menyediakan hook untuk ini:
- Angular — picu cleanup dari
ngOnDestroy - React — kembalikan fungsi cleanup async-safe dari
useEffect - Vue — hapus subscription di
onBeforeUnmount
Setiap
addListenerpemanggilan harus memiliki jalur penghapusan yang sesuai.
Pilih Metode Cleanup yang Tepat
Handle yang dikembalikan adalah pilihan tepat saat satu komponen memiliki satu subscription. removeAllListeners() sangat berguna saat sebuah service menyimpan beberapa listener dan sedang di-reset sepenuhnya.
async function resetUpdates(service: UpdateService) {\nawait service.removeAllListeners();\n}
Jangan panggil metode yang luas dari komponen bersama saat layar lain masih bergantung pada layanan. Jika kepemilikan bersifat lokal, tetap pakai handle remove() individual.
| Situasi | Tindakan yang disarankan |
|---|---|
| Langganan satu komponen | Panggil handle.remove() |
| Shutdown layanan | Panggil removeAllListeners() |
| Registrasi berulang | Inisialisasi guard |
| Payload tidak dikenal | Validasi sebelum dipakai |
Untuk notifikasi Capgo, pisahkan payload update dari event perangkat. Lalu uji registrasi, pengiriman, dan pembersihan secara terpisah — Panduan pelacakan event kustom Capgo punya info lebih lanjut soal sisi integrasi.
Sebelum rilis, periksa tiga hal: unmount benar-benar menghapus handler, promise yang ditolak tertangani, dan tidak ada callback yang bisa memperbarui komponen yang sudah dihancurkan. Disiplin ini menjaga aplikasi reaktif Capacitor tetap responsif di Angular, React, dan Vue.

Dibangun dengan baik contoh API TypeScript dimulai dengan nama yang menggambarkan niat. Gunakan kata kerja untuk method, kata benda untuk interface, dan konsisten dengan suffix seperti Options, Result, dan Event. Nama yang jelas memangkas waktu onboarding karena developer langsung memahami kontraknya tanpa perlu membuka implementasi.
Jaga agar interface publik tetap kecil. Ekspos kemampuan melalui method yang fokus, bukan menumpuk operasi yang kurang berkaitan ke satu objek.
getStatus()membaca state.updateConfig(options)mengubah konfigurasi.addListener(event, callback)berlangganan perubahan.
Tentukan Tipe Input dan Output secara Presisi
Gunakan interface opsi bernama jika parameter berpotensi bertambah:
interface PublishOptions {\nchannel: ‘beta’ | ‘production’;\nrolloutPercent: number;\n}
interface PublishResult {\nversion: string;\naccepted: boolean;\n}
async function publish(\noptions: PublishOptions,\n): Promise
Generics sangat berguna saat API membungkus berbagai payload namun tetap perlu mempertahankan tipe data spesifiknya:
interface ApiResponse
async function request
Tapi jangan tambahkan generics hanya untuk terlihat fleksibel. Generics harus mengekspresikan hubungan nyata antara input dan output — selain itu, interface konkret lebih mudah dibaca dan dipelihara.
Buat state yang tidak valid sulit untuk direpresentasikan, terutama di batas native, jaringan, dan update.
Dokumentasikan perilaku tepat di samping kontraknya. Cakupan izin, unit, promise yang ditolak, field opsional, dan apakah metode berlaku segera atau pada peluncuran berikutnya. Komentar inline harus menjelaskan keputusan, bukan mengulang nama metode.
Atur Code untuk Perubahan
Pisahkan types, logika klien, adapter platform, dan tests ke dalam file yang terstruktur. Export types publik dari satu entry point dan simpan detail implementasi secara privat.
| Aspek | Lokasi yang disarankan |
|---|---|
| Antarmuka publik | types.ts |
| Metode API | client.ts |
| Adapter native | platform/ |
| Test kompatibilitas | tests/ |
Untuk perubahan plugin yang breaking, perkenalkan interface major baru atau layer kompatibilitas, pertahankan metode deprecated untuk sementara, dan tuliskan langkah migrasi. Pelajari lebih lanjut tentang strategi versioning API sebelum mengubah consumer.
Jalankan strict type check dan contract test di CI sebelum shipping. Untuk workflow Capgo, verifikasi nilai channel, kompatibilitas native, signed bundle, dan perilaku rollback sebagai aturan release bertipe — ini menjaga update cepat tetap terkendali saat tim, platform, dan integrasi bertambah.
Bagaimana Cara Menentukan Tipe Hasil Native Dinamis?
Jangan biarkan any menyusup ke code Anda saat metode native mengembalikan data yang tidak terduga. Sebaliknya, tentukan secara eksplisit field yang bisa diandalkan, tandai nilai yang benar-benar opsional dengan ?, dan sanitasi input yang tidak pasti di batas sebelum diproses lebih lanjut.
interface NativeResult { success: boolean; value?: string; }
async function readValue(): Promise
Pendekatan ini menjaga pemanggil Anda tetap aman sambil membuat ketidakpastian menjadi eksplisit dalam tipe itu sendiri. Untuk gambaran lebih luas tentang pola interface ini, lihat kembali membangun API di TypeScript.
Bagaimana Cara Listener Menghindari Unhandled Rejection?
Callback asinkron harus dirancang secara defensif. Tangani kegagalan di dalam listener itu sendiri, bukan mengandalkan sistem event untuk menelan promise yang ditolak secara diam-diam.
const handleUpdate = (event: UpdateEvent): void => { void applyUpdate(event).catch((error: unknown) => { console.error('Update failed', error); }); };
Simpan referensi subscription dan hapus saat komponen unmount. Itu mencegah callback duplikat dan update state yang basi — bagian listener lifecycle membahasnya secara detail.
Setiap listener asinkron perlu punya jalur error dan jalur cleanup.
Bagaimana Cara Melindungi Update Capgo?
Signing keys dan kredensial administratif tetap di server atau sistem CI Anda. Titik. Klien hanya boleh menerima signed bundle dan memakai hasil bertipe untuk menampilkan status — bukan untuk membuat signature.
Sebelum publish, siapkan channel union terpisah, jalankan pemeriksaan kompatibilitas, atur batas rollout, dan rencanakan jalur rollback Anda. Capgo menangani signed delivery, kontrol channel, penerapan next-launch, dan perlindungan rollback untuk Capacitor dan aplikasi Electron. Dokumentasi mereka menunjukkan bagaimana workflow rilis bertipe dapat memperketat pipeline update Anda.