Pustaka TypeScript tidak diterbitkan dalam bentuk berkas .ts-nya, melainkan sebagai JavaScript yang dijalankan oleh runtime dan berkas deklarasi .d.ts yang dibaca compiler serta editor. Topik ini membahas pembangkitan deklarasi lewat opsi declaration, field main dan types pada package.json, pemetaan exports dengan conditions, hingga field files yang membatasi isi paket. Setelah membacanya, sebuah pustaka kecil dapat dipaketkan lengkap dengan tipenya.
Deklarasi hasil kompilasi#
Pustaka mini berikut berisi satu modul konversi suhu yang diekspor lewat sintaks ES modules. Kompilasinya memakai opsi declaration yang menghasilkan satu berkas .d.ts untuk setiap berkas sumber, ditambah rootDir agar tata letak folder sumber tetap terkendali dan outDir untuk menampung hasilnya. Compiler yang dipakai jalur ini bahkan menuntut rootDir dinyatakan secara eksplisit pada tata letak seperti ini, dan tanpanya kompilasi berhenti dengan pesan TS5011 sebelum satu berkas pun dihasilkan.
{
"compilerOptions": {
"strict": true,
"declaration": true,
"rootDir": "src",
"module": "commonjs",
"target": "es2022",
"outDir": "dist"
}
}export interface Suhu {
nilai: number;
satuan: "C" | "F";
}
export function keCelsius(suhu: Suhu): number {
if (suhu.satuan === "F") {
return ((suhu.nilai - 32) * 5) / 9;
}
return suhu.nilai;
}
export function keFahrenheit(suhu: Suhu): number {
if (suhu.satuan === "C") {
return (suhu.nilai * 9) / 5 + 32;
}
return suhu.nilai;
}# mengompilasi pustaka dengan opsi declaration
tsc --project proyek-konversi/tsconfig.json
# melihat isi folder hasil kompilasi
ls proyek-konversi/dist
# membaca berkas deklarasi yang dihasilkan
cat proyek-konversi/dist/konversi.d.tskonversi.d.ts
konversi.js
export interface Suhu {
nilai: number;
satuan: "C" | "F";
}
export declare function keCelsius(suhu: Suhu): number;
export declare function keFahrenheit(suhu: Suhu): number;Berkas konversi.d.ts memuat seluruh tanda tangan publik modul, termasuk interface Suhu dan union literal "C" | "F" yang tetap utuh. Isinya deklarasi tanpa implementasi, sehingga editor dapat menampilkan tipe tanpa membaca isi fungsi. Perhatikan bahwa fungsi dinyatakan lewat declare function yang hanya membawa tanda tangan, tanpa tubuh fungsi sama sekali. Berkas konversi.js di sampingnya adalah kode yang benar-benar dijalankan, dan keduanya berpasangan satu banding satu.
# mengonsumsi hasil kompilasi lewat require biasa
node -e "const { keFahrenheit, keCelsius } = require('./proyek-konversi/dist/konversi.js'); console.log(keFahrenheit({ nilai: 100, satuan: 'C' })); console.log(keCelsius({ nilai: 212, satuan: 'F' }));"212
100Hasil konversinya sesuai hitungan manual, yaitu 100 derajat Celsius setara 212 Fahrenheit, dan 212 derajat Fahrenheit setara 100 Celsius. Bagian runtime inilah yang sampai ke pengguna pustaka, sedangkan tipenya dibawa oleh berkas deklarasi. Keduanya dihasilkan oleh satu perintah tsc yang sama.
Field main dan types pada package.json#
package.json adalah kontrak paket, dan dua field-nya menentukan tempat runtime serta compiler harus mencari pintu masuknya. Field main menunjuk berkas JavaScript yang dijalankan saat paket diimpor, sedangkan field types menunjuk berkas deklarasi yang dibaca TypeScript. Nilai keduanya ditulis relatif terhadap akar paket, dan pada tata letak ini bersebelahan di folder dist. Bagi konsumen, keduanya bekerja pada lapisan berbeda, yaitu bundler dan runtime mengikuti main, sedangkan editor dan tsc mengikuti types saat menampilkan saran dan memeriksa kode.
{
"name": "konversi-suhu",
"version": "1.0.0",
"description": "Konversi satuan suhu Celsius dan Fahrenheit",
"main": "dist/konversi.js",
"types": "dist/konversi.d.ts",
"files": [
"dist"
]
}Tanpa field types, TypeScript masih mencari berkas .d.ts di samping berkas main, sehingga konversi.d.ts tetap ditemukan pada tata letak ini. Field types tetap ditulis karena menyatakan niat secara eksplisit dan tetap dibaca oleh alat yang tidak mencari berkas .d.ts di samping main secara otomatis. Nama typings adalah alias lama yang berperilaku sama, dan cukup salah satu yang dipakai. Pasangan main dan types hanya mampu menyatakan satu pintu masuk, sehingga paket dengan lebih dari satu titik impor memerlukan pemetaan exports pada bagian berikutnya.
exports dengan condition types#
Field exports memetakan jalur impor ke berkas di dalam paket, dan conditions pada tiap entrinya diperiksa dari atas ke bawah. Condition types harus ditulis lebih dahulu agar alat TypeScript menemukan deklarasi sebelum condition default mengambil alih, sedangkan default menjadi jawaban untuk runtime dan alat lain. Pola ini membuat satu entri exports mampu melayani editor, bundler, dan runtime sekaligus tanpa menduplikasi konfigurasi.
{
"exports": {
".": {
"types": "./dist/konversi.d.ts",
"default": "./dist/konversi.js"
}
}
}Begitu exports ada, pemetaan ini diutamakan oleh Node.js modern, bundler, dan TypeScript pada mode resolusi node16 maupun bundler, sementara main dan types tetap berguna untuk alat lama. Kunci "." menunjuk pintu masuk utama paket, dan paket yang lebih besar dapat menambahkan subjalur seperti "./format" di sampingnya tanpa mengubah pintu utama. Urutan condition juga berlaku umum, sehingga condition khusus seperti import atau require dapat disisipkan di antara types dan default bila runtime yang berbeda perlu dibedakan. Dengan pemetaan ini, jalur berkas internal tidak lagi dijanjikan secara publik, sehingga struktur folder dapat diubah tanpa merusak proyek konsumen yang mengikuti pintu resminya.
Daftar files dan pemeriksaan tarball#
Field files adalah daftar putih isi paket, yaitu hanya jalur yang disebutkan yang dikirim ke registry. Daftar dist membatasi paket pada hasil kompilasi, sehingga berkas sumber dan konfigurasi tidak ikut diterbitkan. Isi paket dapat diperiksa tanpa jaringan maupun akun lewat npm pack --dry-run, yang menampilkan isi tarball, yaitu arsip .tgz hasil pemaketan, tanpa benar-benar menerbitkannya.
# memeriksa isi tarball tanpa menerbitkan apa pun
( cd proyek-konversi && npm pack --dry-run )npm notice
npm notice 📦 [email protected]
npm notice Tarball Contents
npm notice 181B dist/konversi.d.ts
npm notice 412B dist/konversi.js
npm notice 208B package.json
npm notice Tarball Details
npm notice name: konversi-suhu
npm notice version: 1.0.0
npm notice filename: konversi-suhu-1.0.0.tgz
npm notice package size: 509 B
npm notice unpacked size: 801 B
npm notice shasum: 6d2633ba2ec98a196ef4749197232299b0ac2220
npm notice integrity: sha512-4ZZcXz7IVdFI1[...]GwQUTQesHRKbQ==
npm notice total files: 3
npm notice
konversi-suhu-1.0.0.tgzDaftar isinya tiga berkas, yaitu dua hasil kompilasi dan package.json. Meskipun files hanya menyebut dist, npm selalu menyertakan package.json beserta berkas metadata seperti README bila ada. Kedua hasil kompilasi terbawa karena dist disebut, sedangkan src dan tsconfig.json tidak muncul. Perintah penerbitan sesungguhnya, npm publish, membutuhkan akun registry dan koneksi jaringan sehingga tidak dijalankan di sini, dan pemeriksaan tarball di atas adalah langkah terakhir sebelum perintah itu dilakukan.
Kesalahan umum#
Kesalahan pertama adalah menerbitkan tanpa deklarasi. Paket yang hanya membawa berkas .js dipakai tanpa tipe, sehingga konsumen TypeScript kehilangan seluruh pemeriksaan terhadap API pustaka. Opsi declaration pada tsconfig mencegahnya karena deklarasi ikut dihasilkan di folder yang sama dengan kodenya.
Kesalahan kedua adalah menunjuk types ke jalur yang tidak ada. Field yang salah tulis membuat pemuatan deklarasi gagal diam-diam pada sebagian alat, sehingga jalurnya perlu diperiksa terhadap isi tarball, bukan hanya terhadap folder kerja. Kesalahan ketiga adalah membiarkan files kosong, karena tanpa daftar putih npm menyertakan seluruh folder paket saat menerbitkan, termasuk berkas sumber, pengujian, dan berkas sisa, sehingga ukuran paket membengkak dan isi internal ikut terbaca. Kesalahan keempat adalah menguji paket hanya dari folder kerjanya sendiri, karena seluruh berkas paket memang tersedia di tempat itu. Pengujian yang lebih akurat dilakukan terhadap isi tarball, sebagaimana dilakukan npm pack --dry-run di atas, atau dengan memasang paket pada proyek contoh yang bersih.
Ringkasan#
- Opsi
declarationmenghasilkan pasangan.jsdan.d.tsuntuk setiap berkas sumber, denganrootDirdanoutDirmenjaga tata letak hasil. - Field
mainmenunjuk titik masuk runtime dantypesmenunjuk titik masuk deklarasi, sedangkantypingsadalah aliasnya. - Pemetaan
exportsdiutamakan oleh resolusi modern, dan conditiontypeswajib ditulis sebelumdefaultagar deklarasi tetap ditemukan. - Field
filesmenjadi daftar putih isi paket, dannpm pack --dry-runmemperlihatkan isi tarball tanpa jaringan maupun akun.
Referensi#
- Publishing — TypeScript Handbook — Panduan resmi menerbitkan berkas deklarasi beserta field package.json yang berkaitan.
- package.json — npm Docs
— Dokumentasi field package.json, termasuk
main,exports, danfiles. - declaration — TypeScript tsconfig Reference
— Referensi opsi
declarationyang membangkitkan berkas.d.ts.