Compiler TypeScript tidak bisa menebak bentuk pustaka yang dipasang lewat npm, karena paketnya umumnya berisi JavaScript tanpa anotasi. Topik ini membahas dua sumber tipe untuk mengisi kekosongan itu, yaitu deklarasi yang dibawa pustaka sendiri dan paket @types dari repositori DefinitelyTyped. Cara npm memuat paket deklarasi, pesan error yang muncul saat deklarasi tidak ada, serta cara menilai kualitas sebuah paket @types dibahas berurutan dengan proyek kecil yang dapat dijalankan ulang. Setelah membacanya, pemilihan paket deklarasi untuk sebuah pustaka dapat dilakukan dengan dasar penilaian yang jelas.
Dua sumber tipe untuk pustaka npm#
Paket npm yang ramah TypeScript berada pada salah satu dari dua keadaan. Pustaka yang menyertakan deklarasinya sendiri menaruh berkas .d.ts di dalam paket dan menunjuknya melalui field types pada package.json, sehingga tidak ada yang perlu dipasang lagi. Pustaka yang tidak menyertakannya dicakup oleh DefinitelyTyped, yaitu repositori komunitas yang menerbitkan satu paket deklarasi @types untuk setiap pustaka yang dibungkusnya.
| Keadaan pustaka | Sumber tipenya | Bentuk berkasnya |
|---|---|---|
| Menyertakan deklarasi sendiri | Berkas .d.ts di dalam paket, ditunjuk field types | paket/index.d.ts |
| Tanpa deklarasi | Paket @types/nama dari DefinitelyTyped | node_modules/@types/nama/index.d.ts |
Pemasangan paket @types memakai npm seperti paket mana pun, dan hasilnya ditaruh pada folder node_modules/@types. Compiler kemudian memuat paket deklarasi ini secara otomatis, yaitu setiap impor nama paket yang tidak menemukan deklarasi di dalam paket pustakanya akan dicarikan pasangannya pada node_modules/@types tanpa perintah impor tambahan. Inilah alasan pengetikan pustaka pihak ketiga terasa bekerja dengan sendirinya setelah paket deklarasinya dipasang.
# tidak-dijalankan
# memasang paket deklarasi komunitas untuk runtime Node.js
npm install --save-dev @types/nodePustaka tanpa deklarasi dan error TS7016#
Proyek proyek-arsip menyimulasikan keadaan yang paling sering dijumpai, yaitu pustaka terpasang tanpa satu pun deklarasi. Folder node_modules-nya disusun manual agar keadaan sesudah pemasangan dapat diulang tanpa jaringan, dan isinya berupa paket pustaka-arsip versi 3.2.0 yang seluruhnya JavaScript murni.
{
"name": "pustaka-arsip",
"version": "3.2.0",
"main": "index.js"
}function buatArsip() {
return { catatan: [] };
}
function tambahCatatan(arsip, catatan) {
arsip.catatan.push(catatan);
return arsip;
}
function cariCatatan(arsip, nomor) {
return arsip.catatan[nomor] ?? null;
}
module.exports = { buatArsip, tambahCatatan, cariCatatan };Berkas pemanggilnya mengimpor pustaka lewat nama paketnya, bukan lewat jalur berkas, persis seperti pemanggilan pustaka pada proyek nyata. Konfigurasi proyeknya memakai strict penuh sehingga parameter yang tipenya tidak dapat disimpulkan akan ditolak.
{
"compilerOptions": {
"strict": true,
"noEmit": true,
"module": "commonjs",
"target": "es2022",
"esModuleInterop": true
}
}// tidak-dijalankan
import { buatArsip, tambahCatatan, cariCatatan } from "pustaka-arsip";
const arsip = buatArsip();
tambahCatatan(arsip, "rapat pagi");
tambahCatatan(arsip, "latihan tipe");
console.log(cariCatatan(arsip, 1));
console.log(cariCatatan(arsip, 9));# memeriksa proyek yang memakai pustaka tanpa deklarasi
tsc --project proyek-arsip --pretty falseproyek-arsip/utama.ts(2,55): error TS7016: Could not find a declaration file for module 'pustaka-arsip'. '/home/kal/my-project/site/content/typescript/ekosistem-js/definitelytyped/proyek-arsip/node_modules/pustaka-arsip/index.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/pustaka-arsip` if it exists or add a new declaration (.d.ts) file containing `declare module 'pustaka-arsip';`Pesan TS7016 di atas memuat dua informasi penting. Modul pustaka-arsip ditemukan pada node_modules, sebab pesannya menyebut jalur berkas index.js yang berhasil diresolusi pada mesin ini, tetapi deklarasinya tidak ada sehingga seluruh modul diperlakukan sebagai any secara implisit. Baris kedua bahkan menyarankan perbaikannya, yaitu memasang paket @types/pustaka-arsip bila ada atau menulis deklarasi declare module sendiri.
# menjalankan program pemanggil pustaka yang bekerja normal
node --no-warnings proyek-arsip/utama.tslatihan tipe
nullPustakanya sendiri berfungsi dengan baik, sebagaimana diperlihatkan keluaran di atas, karena TypeScript tidak pernah mengubah perilaku program. Pencarian nomor 1 mengembalikan catatan kedua dan nomor 9 mengembalikan null, dan deklarasi yang benar seharusnya mencatat dua perilaku tersebut. Kekosongan deklarasi dengan demikian bukan kegagalan pustaka, melainkan pekerjaan pengetikan yang belum selesai.
Dua kualitas paket @types#
Paket @types yang terpasang menghapus TS7016, tetapi menghapus pesan error bukan berarti pemeriksaannya bermanfaat. Dua proyek berikut memasang pustaka yang sama persis dan menjalankan program pemanggil yang sama persis, sementara paket deklarasinya ditulis dengan dua kualitas yang berbeda. Proyek proyek-lemah memakai deklarasi yang menyerahkan segalanya pada any.
proyek-lemah/
├── node_modules/
│ ├── pustaka-arsip/ pustaka yang dipasang
│ └── @types/pustaka-arsip/ paket deklarasi dangkal
│ ├── package.json
│ └── index.d.ts
├── tsconfig.json
└── uji.tsKonfigurasi compiler pada ketiga proyek di topik ini identik, dan program pemanggilnya mengandung dua pemanggilan yang keliru agar kualitas deklarasinya dapat diuji.
{
"name": "@types/pustaka-arsip",
"version": "3.2.0",
"types": "index.d.ts"
}// tidak-dijalankan
export declare function buatArsip(): any;
export declare function tambahCatatan(arsip: any, catatan: any): any;
export declare function cariCatatan(arsip: any, nomor: any): any;// tidak-dijalankan
import { buatArsip, cariCatatan } from "pustaka-arsip";
const arsip = buatArsip();
const catatan = cariCatatan(arsip, 5);
console.log(catatan.length);
console.log(cariCatatan(arsip, "lima"));# memeriksa proyek dengan paket deklarasi yang serba any
tsc --project proyek-lemah --pretty falsePemeriksaan lolos tanpa satu pun pesan, padahal programnya membaca panjang hasil pencarian nomor 5 yang tidak ada lalu memanggil fungsi yang sama dengan string "lima". Deklarasi yang serba any menjawab setiap pertanyaan dengan any, sehingga compiler tidak memiliki kesempatan melaporkan satu pun kesalahan. Paket semacam ini berhasil menghilangkan TS7016, tetapi gagal menjalankan tugas utamanya, yaitu menghadirkan kontrak yang bisa dipegang.
Proyek proyek-tangguh memakai deklarasi yang mencerminkan perilaku pustakanya, termasuk kembalian yang bisa kosong.
// tidak-dijalankan
export interface Arsip {
catatan: string[];
}
export declare function buatArsip(): Arsip;
export declare function tambahCatatan(arsip: Arsip, catatan: string): Arsip;
export declare function cariCatatan(arsip: Arsip, nomor: number): string | null;// tidak-dijalankan
import { buatArsip, cariCatatan } from "pustaka-arsip";
const arsip = buatArsip();
const catatan = cariCatatan(arsip, 5);
console.log(catatan.length);
console.log(cariCatatan(arsip, "lima"));# memeriksa proyek dengan paket deklarasi yang teliti
tsc --project proyek-tangguh --pretty falseproyek-tangguh/uji.ts(6,13): error TS18047: 'catatan' is possibly 'null'.
proyek-tangguh/uji.ts(7,32): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.Program yang sama kini ditolak pada dua tempat. Deklarasi yang menyatakan kembalian string | null menuntut penanganan null sebelum panjangnya dibaca, sedangkan tipe parameter number menolak argumen string. Kedua temuan itu sesuai dengan perilaku pustaka yang sebenarnya, sehingga paket deklarasi yang teliti langsung mengubah dua kebiasaan buruk menjadi dua perbaikan yang terarah.
Menilai kualitas pengetikan sebuah paket#
Kualitas paket @types bervariasi dari deklarasi serba any sampai pengetikan yang mencerminkan pustakanya seluruhnya, sehingga pemakainya memerlukan kriteria penilaian sebelum mempercayainya. Tabel berikut merangkum pertanyaan yang perlu diajukan terhadap setiap paket.
| Aspek | Pertanyaan yang diajukan |
|---|---|
| Kelengkapan | Apakah fungsi, kelas, dan opsi utama pustaka semuanya terdeklarasi? |
| Ketepatan | Apakah parameter bertipe spesifik dan penggunaan any sedikit? |
| Kejujuran null | Apakah kembalian yang bisa kosong dinyatakan dengan null atau undefined? |
| Kesesuaian versi | Apakah nomor versi paket mengikuti versi pustaka yang terpasang? |
| Pemeliharaan | Apakah perbaikan masih digabung dan penanggung jawabnya aktif? |
| Ukuran pemakai | Seberapa banyak proyek yang memakainya sehingga deklarasinya teruji luas? |
Kesesuaian versi memiliki aturan tersendiri pada DefinitelyTyped. Nomor versi paket @types mengikuti versi pustaka yang dicakupnya, sehingga @types/pustaka-arsip versi 3.2.0 pada contoh ini menjanjikan deklarasi untuk pustaka-arsip versi 3.2.0. Pustaka dengan sejarah panjang memiliki paket terpisah untuk versi lamanya, sehingga proyek yang masih memakai versi tua perlu memilih paket yang sesuai dan bukan yang terbaru.
Dua proyek pada bagian sebelumnya memberi contoh ujung spektrumnya. Deklarasi serba any memenuhi aspek kelengkapan secara formal karena semua nama tertulis, tetapi gagal pada ketepatan dan kejujuran null, sedangkan deklarasi teliti menghasilkan laporan yang sesuai dengan perilaku pustaka. Ukuran pemakai melengkapi penilaian ini, karena paket yang dipakai ribuan proyek biasanya telah teruji pada lebih banyak keadaan daripada yang mampu diuji satu orang.
Kesalahan umum#
Kesalahan berikut sering muncul saat memakai paket deklarasi komunitas.
- Memasang paket
@typesuntuk pustaka yang sudah membawa deklarasinya sendiri. Dua sumber tipe untuk nama modul yang sama hanya menambah duplikasi, dan salah satunya pasti dibiarkan basi. Perbaikannya berupa memeriksa fieldtypespada package.json pustaka lebih dahulu. - Menjawab TS7016 dengan
@ts-ignoreatau anotasianyalih-alih deklarasi. Cara pintas itu menutup satu baris, sedangkan masalah utamanya tetap ada dan pemanggil lain tetap kehilangan tipe. Perbaikannya berupa memasang paket@typesyang sesuai atau menulis deklarasinya. - Menganggap paket
@typesmengubah perilaku program saat berjalan. Paket deklarasi hanya dipakai compiler dan language server, sehingga memasangnya tidak menyembuhkan bug apa pun. Perbaikannya berupa memperlakukan paket deklarasi sebagai lapisan pemeriksaan, bukan lapisan eksekusi. - Memilih paket
@typesyang terbaru tanpa mencocokkan versi pustakanya. Deklarasi untuk versi yang lebih baru dapat menjanjikan fungsi yang belum ada pada pustaka terpasang. Perbaikannya berupa mencocokkan nomor versi keduanya sebelum dipercaya.
Ringkasan#
- Tipe pustaka npm berasal dari berkas
.d.tsbawaan paket atau dari paket@typesDefinitelyTyped yang ditaruh npm pada node_modules/@types. - Error TS7016 berarti modul ditemukan tanpa deklarasi, sehingga seluruh modul diperlakukan
anydan pemeriksaan tipe kehilangan perannya. - Paket
@typesyang serbaanymenghapus pesan error sekaligus perlindungannya, sedangkan deklarasi teliti menangkap kesalahan pemanggil yang nyata. - Kualitas paket dinilai dari kelengkapan, ketepatan tipe, kejujuran null, kesesuaian versi, pemeliharaan, dan ukuran pemakainya.
Referensi#
- DefinitelyTyped — definitelytyped.org — Situs resmi repositori paket deklarasi komunitas beserta aturan penerbitannya.
- npm-install — npm Docs — Dokumentasi perintah pemasangan paket yang dipakai untuk paket @types.
- Introduction — TypeScript Handbook — Peran berkas deklarasi sebagai sumber tipe pustaka JavaScript.