Kembali ke Blog

Saya Migrasi Project Client ke Compiler Native TypeScript 7: Apa yang Beneran Berubah

#typescript#compiler#tooling
Saya Migrasi Project Client ke Compiler Native TypeScript 7: Apa yang Beneran Berubah

TypeScript 7.0 udah GA bulan ini dengan compiler baru yang ditulis ulang pakai Go — internal-nya disebut tsgo — dan angka yang diulang-ulang semua orang itu “10x lebih cepat.” Saya udah beberapa kali kena kecewa sama pengumuman tooling yang kedengeran keren di blog post terus begitu nyentuh codebase beneran yang udah tiga tahun numpuk keanehan, jadi berantakan. Jadi daripada nulis hot take dari changelog doang, saya beneran pasang di salah satu project client saya dan catat apa yang kejadian.

Project yang saya pilih itu dashboard admin ukuran medium, beberapa ratus file TypeScript, React di frontend, dan lumayan banyak type yang di-share sama backend. Nggak ada yang eksotis, tapi umurnya udah cukup buat numpuk beberapa hal — beberapa type utility custom, ada any yang harusnya udah lama saya bersihin, build pipeline yang jarang disentuh sejak awal setup. Persis jenis project yang kalau compiler-nya diganti total, bisa dua kemungkinan: diem-diem hemat waktu tiap hari, atau error di sudut yang nggak saya perkirakan.

Upgrade-nya sendiri nggak sedramatis yang saya kira. npm install typescript@7 plus ganti referensi binary tsc yang di-hardcode, dan sebagian besar command sehari-hari langsung jalan. Penyesuaian yang lebih besar itu mental: tsgo bukan flag di compiler lama, itu type checker yang ditulis ulang total pakai Go, jadi ekspektasi jujur di awal harusnya “ini berperilaku kayak TypeScript, bukan berarti identik byte-per-byte sama compiler lama di setiap edge case.” Framing itu ternyata penting buat cara saya baca error-error yang muncul.

Selisih build time-nya beneran nyata, dan jenis nyata yang kerasa tanpa perlu stopwatch. Clean build di project ini dari yang tadinya lebih dari 40 detik jadi di bawah 6 detik. Incremental build pas lagi aktif develop malah kemenangan yang lebih kerasa di praktik — jarak antara save file sampai muncul type error di editor dari yang tadinya “cukup lama buat sempet ngecek Slack” jadi hampir instan. Kalau kamu kerja di beberapa project sekaligus dalam sehari kayak saya, bedanya numpuk jadi sore yang jauh lebih nggak bikin frustrasi, bukan cuma grafik benchmark yang kelihatan bagus.

Sisi yang masih agak kasar itu muncul di ekosistem tooling sekitar compiler-nya, bukan di compiler-nya sendiri. Beberapa rule ESLint yang nge-rely ke TypeScript language service kelakuannya sedikit beda sampai saya update typescript-eslint ke versi yang eksplisit support 7.0. Satu transformer custom yang saya tulis bertahun-tahun lalu buat step code-generation belum ada versi native-compiler-nya, jadi masih harus jalan lewat compiler JS lama sebagai step terpisah — nyebelin dikit tapi masih bisa dikerjain sebagai kondisi interim. Pelajarannya bukan “jangan upgrade,” tapi “cek versi plugin dulu sebelum nyentuh project client, bukan sesudahnya.”

Editor experience itu bagian yang tadinya saya paling skeptis, dan malah paling bikin saya yakin. TS server bawaan VS Code secara historis emang jadi hal yang bikin lag di monorepo besar, dan saya udah nebak compiler native bakal bantu di situ juga, tapi saya nggak nyangka bakal sebanyak ini. Autocomplete di file dengan import chain yang dalem, dari yang tadinya kerasa nge-stutter setengah detik jadi kerasa instan. Bukan metrik yang dibenchmark siapa-siapa, tapi itu hal yang beneran ngubah rasanya kerja di editor delapan jam sehari.

Saya sempet nemu satu hal yang bikin saya deg-degan cukup buat mikir lebih pelan: ada beberapa edge case narrowing di generic-heavy utility type yang resolve-nya sedikit beda antara compiler lama dan baru. Nggak ada yang ngubah behavior runtime, dan nggak ada yang bisa dibilang lebih salah di compiler baru — tapi itu persis jenis diff halus yang bisa diem-diem nyembunyiin bug beneran kalau kamu nggak merhatiin pas transisi. Saya jalanin full diff tsc --noEmit antara output compiler lama dan baru sebelum merge, bukan cuma cek “build-nya lolos apa nggak,” dan saya bakal saranin siapapun yang migrasi buat ngelakuin hal yang sama.

Saya nggak rollout ini ke semua sekaligus, dan saya juga nggak saranin siapapun ngelakuin itu. Urutan rollout saya sendiri: side project kecil saya duluan, karena kalau ada yang salah di situ dampaknya cuma saya sendiri yang kesel semalem. Baru dashboard client ini, di branch terpisah, dengan compiler lama masih available sebagai fallback di CI sampai saya beneran yakin. Setelah itu baru saya mulai rencanain buat codebase client yang lebih besar dan lebih type-heavy yang saya maintain, dan itu sengaja saya lakuin lebih pelan karena project itu punya lebih banyak custom tooling yang nyambung ke build-nya.

Hal yang terus kepikiran sama saya: ini jenis peningkatan tooling yang bagus, yang nggak minta kamu ngubah cara nulis kode. Banyak churn tooling AI dan framework yang saya tulis di blog ini minta perubahan behavior beneran, mental model baru, cara mikir baru soal stack kamu. Yang ini cuma bikin hal yang udah kamu kerjain jadi lebih cepet, dengan cost adopsi yang kecil kalau kamu cek compatibility plugin dulu. Langka banget di industri ini sampai layak disebut sendiri, terlepas dari apakah angka 10x-nya persis sama kayak yang bakal kamu liat di project kamu sendiri.

Rekomendasi jujur saya buat orang lain yang lagi mikirin ini: coba dulu di project beneran kamu yang paling kecil, bukan toy repo dan bukan codebase client kamu yang paling besar. Toy repo nggak bakal nunjukin masalah compatibility plugin yang beneran ngegigit, dan codebase paling besar kamu itu tempat yang salah buat kena kejutan. Sesuatu di tengah-tengah ngasih kamu gambaran cepat dan low-risk soal apakah kombinasi build tool, linter, dan transformer custom kamu udah siap.

Apa saya bakal balik ke compiler lama buat project ini? Nggak — kemenangan build time-nya aja udah cukup buat mempertahankan yang baru, walaupun ada friksi plugin yang saya alamin. Tapi saya seneng saya ngedeketinnya kayak gini: sebagai migrasi beneran dengan rencana rollback, bukan cuma ganti nomor versi di package.json terus berharap nggak ada yang rusak. Di codebase yang blast radius-nya nggak sepenuhnya kamu kontrol, “kayaknya sih aman” itu bukan rencana.