Di TypeScript, sebuah promise bertipe Promise<T>, dengan T adalah tipe nilai yang dihasilkannya saat resolve. Fungsi yang mengembalikan promise mendeklarasikannya di tipe kembaliannya, dan nilai yang kamu dapat dari then atau await bertipe T.
Mekanisme promise (state, antrean microtask, chaining) adalah JavaScript biasa, dibahas di promise JavaScript. Halaman ini membahas tipenya.
Memberi Tipe pada new Promise dan resolve
Kalau new Promise adalah nilai kembalian fungsi yang tipe kembaliannya dideklarasikan, T berasal dari situ. Kalau berdiri sendiri, TypeScript tidak menyimpulkan T dari pemanggilan resolve, dan kamu mendapat Promise<unknown>. Berikan argumen tipenya secara eksplisit:
Ada dua detail. resolve diberi tipe dari T, jadi resolve("42") di Promise<number> adalah error kompilasi. Lalu resolve() tanpa argumen hanya diperbolehkan kalau T memuat void: di Promise<number> hasilnya error TS2794 (Expected 1 arguments, but got 0. Did you forget to include 'void' in your type argument to 'Promise'?).
Sisi reject tidak bertipe. Tidak ada Promise<T, E>: sebuah promise bisa reject dengan nilai apa pun.
then, catch dan finally
Setiap then mengembalikan promise baru yang tipenya ditentukan oleh apa yang dikembalikan callback-nya. Kalau callback mengembalikan promise, TypeScript membukanya, jadi kamu tidak akan pernah mendapat Promise<Promise<T>>.
Parameter callback catch diberi tipe any di standard library, bukan unknown. Tidak ada yang mencegahmu menulis e.message pada nilai yang mungkin berupa string. Anotasi sebagai unknown, seperti di atas, lalu persempit tipenya sebelum dipakai. try/catch di sekitar await lebih baik: dengan strict, variabel catch-nya sudah bertipe unknown (lihat penanganan error).
Promise.all Mengembalikan Tuple
Kalau diberi array literal berisi promise dengan tipe berbeda, Promise.all mengembalikan promise berisi tuple, dengan setiap posisi mempertahankan tipenya sendiri:
Nilai yang bukan promise boleh dicampur dan diteruskan apa adanya. Promise.all langsung reject begitu satu input reject, dan hasil lainnya hilang. Promise.race resolve atau reject mengikuti yang pertama selesai dan bertipe union dari semua input; Promise.any resolve dengan keberhasilan pertama dan reject dengan AggregateError hanya kalau semua input gagal.
Promise.allSettled dan Tipe Hasilnya
Promise.allSettled menunggu setiap input dan tidak pernah reject. Setiap hasil adalah PromiseSettledResult<T>, sebuah union yang kamu persempit dengan field status:
r.value hanya ada setelah pengecekan status, karena varian rejected tidak punya value. reason bertipe any, dengan alasan yang sama seperti di catch. filter memakai type predicate supaya array hasil saringannya bertipe hasil fulfilled.
Membungkus API Callback dalam Promise
API lama melaporkan hasilnya lewat callback, sering dengan gaya Node (err, result) => void. Bungkus sekali dalam fungsi yang mengembalikan promise bertipe, dan sisa kodenya bisa memakai await:
Di Node, util.promisify melakukan hal ini untuk fungsi yang mengikuti konvensi (err, result), dan banyak module bawaan sudah punya versi promise (node:fs/promises, node:timers/promises).
Kesalahan Umum
- Mengembalikan
Tpadahal signature-nyaPromise<T>, atau sebaliknya. Fungsi non-async yang dideklarasikanPromise<User>harus mengembalikan promise; fungsiasyncmengembalikannya secara otomatis. - Lupa menangani promise. Pemanggilan seperti
save(user);tanpaawait,thenataucatchtetap lolos kompilasi, dan rejection-nya menjadi unhandled rejection (yang secara default menghentikan proses Node). Aturan typescript-eslintno-floating-promisesmenangkap kasus seperti ini. - Memercayai tipe
.catch((e) => ...).e-nya bertipeany. Anotasi sebagaiunknown. - Memakai
new Promisedi sekitar sesuatu yang sudah mengembalikan promise. Cukup return atauawaitpromise yang sudah ada.
Pertanyaan yang sering diajukan
Apa itu Promise<T> di TypeScript?
Promise<T> adalah tipe promise yang resolve dengan nilai bertipe T. Fungsi yang mengembalikan Promise<string> memberikan promise yang callback then-nya, atau await-nya, menghasilkan string. Promise yang resolve tanpa nilai adalah Promise<void>.
Bagaimana cara memberi tipe pada new Promise di TypeScript?
Berikan argumen tipenya: new Promise<number>((resolve, reject) => ...). Tanpa itu, TypeScript tidak bisa menyimpulkan nilainya dari pemanggilan resolve dan hasilnya Promise<unknown>. Untuk promise yang resolve tanpa nilai apa pun, pakai new Promise<void>(resolve => ...) supaya resolve() tanpa argumen diperbolehkan.
Apa tipe error di catch sebuah promise?
any. Parameter reason milik callback catch diberi tipe any di standard library, karena apa saja bisa di-throw atau di-reject. Anotasi sendiri sebagai unknown (.catch((e: unknown) => ...)) lalu persempit dengan instanceof Error sebelum memakainya.
Bagaimana Promise.all bekerja dengan tipe di TypeScript?
Promise.all pada array literal mengembalikan tipe tuple dengan satu elemen per input, sesuai urutannya: Promise.all([getUser(), getCount()]) adalah Promise<[User, number]>, jadi destructuring memberi setiap nilai tipenya sendiri. Pada array bertipe sama, T[], hasilnya Promise<T[]>.
Apa perbedaan Promise.all dan Promise.allSettled?
Promise.all langsung reject begitu salah satu input reject. Promise.allSettled selalu resolve, dengan array berisi object PromiseSettledResult<T>: { status: "fulfilled", value } atau { status: "rejected", reason }. Cek status untuk mempersempit tipe masing-masing.