value satisfies Type mengecek saat kompilasi bahwa value cocok dengan Type, lalu membiarkan tipe milik nilai itu sendiri, yang lebih tepat, tetap seperti semula. Anotasi akan mengganti tipe yang tepat itu dengan Type; satisfies memvalidasi tanpa melebarkan tipe.
satisfies tetap melakukan pengecekan: warna yang hilang, key yang salah eja seperti bleu, atau nilai seperti true adalah error kompilasi di baris itu. Operator ini ada sejak TypeScript 4.9 dan, seperti setiap anotasi tipe, dihapus dari JavaScript yang dihasilkan.
Masalah yang Diselesaikan satisfies
Dengan anotasi tipe, tipe variabel adalah anotasinya. Compiler melupakan apa yang dilihatnya di literal. Di sini palet yang sama diberi anotasi, dan sekarang TypeScript tidak lagi tahu bahwa green adalah string:
Compiler melaporkan:
index.ts(11,27): error TS2339: Property 'toUpperCase' does not exist on type 'Color'.
Property 'toUpperCase' does not exist on type '[number, number, number]'.
Sebelum TypeScript 4.9, pilihannya adalah: beri anotasi lalu persempit tipe secara manual di mana-mana (typeof palette.green === "string"), atau lewati anotasi dan kehilangan pengecekannya. satisfies memberi keduanya. Ganti : Record<ColorName, Color> dengan satisfies Record<ColorName, Color> setelah kurung kurawal penutup dan kodenya berjalan.
satisfies vs Anotasi Tipe vs as
Object pengaturan yang sama, ditulis dengan tiga cara:
as meloloskan lang yang hilang, dan asserted.lang bernilai undefined saat runtime padahal tipenya bilang string. Hapus lang dari dua baris lainnya dan keduanya gagal dengan TS2741, Property 'lang' is missing in type ....
Anotasi const x: T = v | Assertion v as T | v satisfies T | |
|---|---|---|---|
| Property yang hilang | error | diizinkan | error |
| Property tambahan (object literal) | error | diizinkan | error |
| Tipe property yang salah | error | hanya kalau tipenya tidak beririsan | error |
Tipe x sesudahnya | T | T | tipe hasil inferensi dari v |
Literal type ("dark", 8080) | dilebarkan menjadi T | dilebarkan menjadi T | dipertahankan selama T mengizinkannya |
Key dari Record<string, ...> | string apa pun (salah ketik lolos kompilasi) | string apa pun | tepat key yang ditulis |
| Efek saat runtime | tidak ada | tidak ada | tidak ada |
Patokan praktisnya: beri anotasi kalau kamu ingin variabelnya punya tipe yang dideklarasikan (nilai yang akan di-assign ulang, API publik), dan pakai satisfies kalau kamu ingin pengecekan tetapi tipe milik nilai itu sendiri lebih berguna.
Menangkap Kesalahan di Object Literal
satisfies menjalankan pengecekan assignability secara penuh, termasuk excess property check, jadi salah ketik di key menjadi error:
type Route = { path: string; method: "GET" | "POST" };
const home = { path: "/", metod: "GET" } satisfies Route;
// error TS2561: Object literal may only specify known properties, but 'metod' does not exist in type 'Route'. Did you mean to write 'method'?
Pengecekan ini juga memberi literal itu contextual type, sama seperti anotasi. Itu penting dalam dua hal. String literal dipertahankan sebagai literal type kalau tipe targetnya mengharapkannya: { path: "/", method: "GET" } satisfies Route punya method: "GET", sedangkan object yang sama tanpa anotasi akan menyimpulkan method: string. Lalu parameter callback disimpulkan dari tipe target:
Key Record Tetap Diketahui
Pemakaian yang umum adalah tabel lookup. Kalau dianotasi sebagai Record<string, T>, setiap string adalah key yang valid dan salah ketik tetap lolos kompilasi, lalu menghasilkan undefined saat runtime. Dengan satisfies, nilainya tetap dicek terhadap T, tetapi tipe variabelnya mendaftar tepat key yang kamu tulis:
keyof typeof endpoints hanya berguna karena key-nya bertahan. Dengan anotasi, hasilnya hanya string.
Untuk mewajibkan himpunan key yang tetap, pastikan nilainya memenuhi Record atas sebuah union: satisfies Record<"dev" | "prod", string> melaporkan prod yang hilang dengan TS2741 dan staging yang tidak dikenal dengan TS2353.
as const satisfies
as const dan satisfies bisa digabungkan. Tulis as const lebih dulu: ia membuat nilainya readonly secara mendalam dengan literal type, lalu satisfies mengecek nilai yang persis itu.
Setiap route dicek terhadap Route (method: "PUT" akan menjadi error), dan tuple berisi literal type tetap tersedia, jadi Path adalah union dari path yang sebenarnya. Pakai readonly Route[] (atau ReadonlyArray<Route>) sebagai target, karena array as const bersifat readonly.
Object Konfigurasi
Konfigurasi adalah tempat satisfies paling berguna: bentuknya harus benar, dan kode di tempat lain menginginkan nilai yang persis.
Lupakan entri production, salah eja logLevel, atau tulis logLevel: "verbose", dan compiler menunjuk baris yang tepat. Pola yang sama cocok untuk file *.config.ts: export default { ... } satisfies SomeConfig mengecek seluruh file sementara object yang di-export tetap mempertahankan nilai literalnya.
Kapan Tidak Memakai satisfies
- Variabelnya akan di-assign ulang.
let cfg = { port: 3000 } satisfies { port: number | string }membericfgtipe{ port: number }, jadicfg = { port: "80" }di kemudian hari gagal (TS2322). Beri anotasi pada variabel yang memang ingin kamu ubah. - Kamu memang menginginkan tipe yang dideklarasikan. Untuk nilai kembalian fungsi atau konstanta yang di-export sebagai bagian dari API, tipe anotasinya adalah kontraknya, dan membocorkan literal type yang persis bisa membuat perubahan di kemudian hari menjadi breaking change.
- Nilainya bukan literal.
satisfiespaling bermanfaat pada object dan array literal. Pada variabel atau hasil pemanggilan fungsi, ia hanya pengecekan assignability biasa, yang sudah diberikan oleh anotasi.
Pertanyaan yang sering diajukan
Apa fungsi satisfies di TypeScript?
expression satisfies Type mengecek saat kompilasi bahwa ekspresi itu assignable ke Type, melaporkan property yang hilang, property tambahan, dan tipe nilai yang salah, lalu membiarkan tipe hasil inferensi ekspresi itu tetap seperti semula. Kamu mendapat keamanan anotasi sekaligus ketepatan inferensi. Operator ini dihapus dari output JavaScript.
Apa perbedaan satisfies dan anotasi tipe?
Keduanya mengecek nilainya. Anotasi (const x: T = ...) lalu memberi variabel itu tipe T, sehingga apa yang diketahui compiler tentang nilainya terlupakan (literal type, anggota union mana yang dipakai setiap property, key apa saja yang ada). satisfies T mempertahankan tipe hasil inferensi, jadi x.someKey diketahui ada dan property string | number yang berisi string bertipe string.
Apa perbedaan satisfies dan as di TypeScript?
as adalah assertion: ia menimpa tipe dan hampir tidak mengecek apa pun, jadi property yang hilang tidak ketahuan. satisfies adalah pengecekan: nilainya harus benar-benar cocok dengan tipe itu, dan tipe hasil inferensinya sendiri tetap dipertahankan. Kalau keduanya sama-sama lolos kompilasi, satisfies adalah pilihan yang lebih aman.
Apa arti as const satisfies?
Keduanya diterapkan: as const membuat nilainya readonly secara mendalam dengan literal type, lalu satisfies mengecek hasil itu terhadap sebuah tipe. Tulis as const lebih dulu: const routes = [...] as const satisfies readonly Route[];. Variabelnya mempertahankan literal type yang persis untuk dipakai nanti, dan entri yang salah tetap menjadi error kompilasi.
Versi TypeScript mana yang menambahkan satisfies?
TypeScript 4.9, yang dirilis pada November 2022. Ini sintaks biasa yang bisa dihapus, jadi ia juga berjalan dengan type stripping bawaan Node, dan semua versi TypeScript saat ini (termasuk 7) mendukungnya.