Dulu saya sengaja menyampaikan pendapat ini secara provokatif: TypeScript adalah bahasa terbaik untuk Codex. Sekarang saya akan membuatnya lebih presisi. Untuk pekerjaan frontend dan full-stack production yang saya lakukan, TypeScript adalah lingkungan tempat Codex paling mudah dikendalikan, diverifikasi, dan digunakan dengan kepercayaan yang masuk akal.
Kata terpenting di sini bukan “TypeScript”, tetapi kontrol. AI coding agent sangat bagus menghasilkan kode yang terlihat masuk akal. Engineering production menuntut lebih: kode harus mengikuti kontrak yang sudah ada, mempertahankan behavior, aman melewati refactor, dan gagal dengan jelas ketika asumsi salah. TypeScript membuat lebih banyak batasan itu bisa dibaca dan diperiksa mesin dibanding JavaScript biasa.
Apa yang sebenarnya dibutuhkan Codex dari codebase
Prompt yang baik membantu, tetapi prompt hanya salah satu sumber konteks. Codebase itu sendiri bisa membuat tugas mudah dipahami atau memaksa model menebak. Dalam praktik, lingkungan terbaik adalah yang membuat asumsi penting terlihat dan otomatis diperiksa.
- Function signature menentukan input dan output yang valid.
- Interface dan type memperjelas bentuk object domain.
- Union dan enum membatasi state yang sah.
- Compiler mengubah banyak asumsi salah menjadi error konkret segera setelah edit.
AI agent tidak harus memahami seluruh aplikasi secara sempurna jika aplikasi sendiri bisa “menolak” ketika kontraknya dilanggar. Semakin pendek feedback loop, semakin sedikit ruang untuk tebakan yang terlalu percaya diri.
Type adalah konteks yang bisa dieksekusi, bukan sekadar dokumentasi
TypeScript yang baik mendokumentasikan intent untuk manusia. Dalam workflow otomatis, nilainya lebih besar karena dokumentasi itu dapat diverifikasi. Contoh kecil:
type PaymentResult =
| { ok: true; receiptId: string }
| { ok: false; code: "declined" | "timeout" };
function getReceiptId(result: PaymentResult) {
if (result.ok) return result.receiptId;
return result.receiptId;
// TypeScript: Property 'receiptId' does not exist
// on the failure branch.
}Di JavaScript, kesalahan yang sama bisa terlihat wajar sampai branch tersebut benar-benar dijalankan saat runtime. TypeScript dapat menolak asumsi itu sebelum merge. Bagi Codex, compiler error bukan sekadar garis merah di editor, tetapi sinyal spesifik tentang apa yang salah dipahami model.
Karena itu saya lebih suka domain type yang eksplisit daripada struktur terlalu luas seperti Record<string, any>. Semakin akurat type menggambarkan realitas, semakin berguna codebase sebagai konteks untuk developer maupun AI.
Compiler mengubah kesalahan menjadi feedback loop
Saya tidak percaya pada workflow “minta Codex menulis kode lalu terima jawaban pertama”. Proses yang saya percaya bersifat iteratif:
task → inspect → edit → typecheck → lint → test → review diffUrutan ini membosankan, dan justru itu kekuatannya. Setelah setiap perubahan penting, lingkungan memberi respons. Type error menangkap kontrak yang rusak. Lint menangkap kelas masalah lain. Test memverifikasi behavior yang tidak dapat diekspresikan oleh type. Diff akhir tetap diperiksa manusia.
Prompt cerdas bisa memperbaiki percobaan pertama. Verification loop yang kuat memperbaiki setiap percobaan. Untuk production, itu jauh lebih penting.
Refactor besar adalah tempat TypeScript paling bernilai
Edit kecil dan terisolasi mudah bagi hampir semua coding assistant. Kasus sulit adalah perubahan yang menyebar ke puluhan file: mengganti nama field domain, mengubah response API, memperketat component props, memecah union, atau mengganti abstraction lama.
Dengan TypeScript, breaking change membuat peta asumsi yang terdampak. Compiler menunjukkan lokasi yang masih memakai kontrak lama. Codex dapat mengerjakan daftar itu lalu memverifikasi ulang setiap putaran. Ini tidak membuat refactor otomatis benar, tetapi membuat blast radius terlihat.
Dalam codebase yang longgar, dependency yang terlewat bisa baru muncul sebagai bug di screen yang tidak pernah dibuka selama development.
Hal yang tidak bisa diselamatkan TypeScript
TypeScript adalah guardrail, bukan bukti bahwa program benar. Ia tidak mencegah beberapa kegagalan penting:
- Business logic salah: kode yang typed sempurna masih bisa menghitung hasil yang salah.
- Input runtime: API, database, form, atau third-party service dapat mengirim data berbeda dari asumsi compile-time.
- Konteks produk yang kurang: compiler tidak tahu mengapa suatu flow ada atau edge case mana yang penting bagi user.
- Security dan architecture: type valid tidak menjamin authorization, caching, boundary database, atau infrastructure yang benar.
Karena itu runtime validation, test, logging, observability, dan review tetap diperlukan. Typecheck bersih bukan berarti feature sudah benar.
Workflow yang saya gunakan untuk perubahan berbantuan AI
- Beri tugas tujuan yang sempit. Apa yang berubah, apa yang tidak, dan apa acceptance criteria-nya.
- Minta Codex menginspeksi sebelum edit. Type yang ada, call site, test, dan module sekitar sering lebih berguna daripada prompt panjang.
- Pilih perubahan koheren terkecil. Diff fokus lebih mudah diverifikasi daripada rewrite “membantu” pada kode yang tidak terkait.
- Jalankan typecheck dan lint segera. Saya ingin structural error muncul saat perubahan masih kecil.
- Jalankan test relevan dan tambahkan test jika behavior berubah. Type memvalidasi kontrak; test memvalidasi behavior.
- Review diff akhir secara manual. Naming, architecture, duplikasi, edge case, dan apakah implementasi benar-benar menyelesaikan masalah awal.
Kapan JavaScript masih cukup
Ini bukan argumen bahwa JavaScript buruk. Untuk script kecil, prototype sekali pakai, automation sederhana, atau kode dengan sedikit shared state, struktur tambahan TypeScript mungkin tidak memberi banyak nilai. Project JavaScript dengan test kuat dan convention jelas juga dapat menjadi lingkungan AI yang sangat baik.
Klaim saya lebih sempit: semakin besar, panjang umur, dan kolaboratif codebase, semakin tinggi nilai constraint yang dapat diperiksa mesin. Dan pada titik yang sama, kesalahan AI juga menjadi lebih mahal.
Alasan sebenarnya saya memilih TypeScript bersama Codex
TypeScript tidak membuat Codex lebih pintar. TypeScript membuat lingkungan lebih sulit menerima asumsi buruk.
Di production saya tidak hanya ingin agent yang kreatif; saya ingin agent yang bekerja dalam sistem yang terus memberitahunya saat ia salah. Type, compiler error, lint, test, dan human review bersama-sama membentuk sistem itu.
Jadi ketika saya mengatakan TypeScript bekerja sangat baik dengan Codex, ini bukan fanatisme bahasa. Ini tentang feedback cepat yang dapat diverifikasi mesin: lebih sedikit ambiguitas, blast radius lebih kecil, refactor lebih aman, dan—jika verifikasi dilakukan serius—kecepatan engineering yang jauh lebih dapat diandalkan.