5 Perintah Pengembang TypeScript

gambar


Semakin banyak proyek dan tim yang menggunakan TypeScript. Namun, hanya menerapkan TypeScript dan memeras yang terbaik adalah hal yang sangat berbeda.


Saya menyajikan kepada Anda daftar praktik terbaik tingkat tinggi untuk menggunakan TypeScript yang akan membantu Anda memaksimalkan bahasa ini.


Jangan berbohong


Jenis adalah kontrak. Apa artinya ini? Ketika Anda mengimplementasikan suatu fungsi, tipenya menjadi janji bagi pengembang lain (atau untuk diri Anda sendiri di masa depan!) Bahwa, ketika dipanggil, fungsi ini akan mengembalikan jenis nilai tertentu.


Dalam contoh berikut, jenis fungsi getUser memastikan bahwa ia mengembalikan objek yang selalu memiliki dua properti: name dan age .


 interface User { name: string; age: number; } function getUser(id: number): User { /* ... */ } 

TypeScript adalah bahasa yang sangat fleksibel. Ini memiliki banyak kompromi yang dirancang untuk memfasilitasi pengenalan bahasa. Misalnya, ini memungkinkan Anda untuk mengimplementasikan fungsi getUser seperti ini:


 function getUser(id: number): User { return { age: 12 } as User; } 

Jangan lakukan itu! Ini adalah SALAH. Dengan membuat kode seperti itu, Anda BERBOHONG ke pengembang lain (yang akan menggunakan fungsi Anda dalam fungsinya). Mereka berharap objek yang dikembalikan oleh getUser akan selalu memiliki semacam bidang name . Tapi dia tidak ada di sana! Selanjutnya, apa yang terjadi ketika kolega Anda menulis getUser(1).name.toString() ? Anda tahu betul bahwa ...


Di sini, tentu saja, kebohongan itu tampak jelas. Namun, bekerja dengan basis kode besar, Anda akan sering menemukan diri Anda dalam situasi di mana nilai yang ingin Anda kembalikan (atau lewati) hampir cocok dengan jenis yang diharapkan. Butuh waktu dan usaha untuk menemukan penyebab ketidakcocokan jenis , dan Anda sedang terburu-buru ... sehingga Anda memutuskan untuk menggunakan pengecoran jenis.


Namun, dengan melakukan ini, Anda melanggar kontrak suci . Lebih baik mengambil waktu dan memahami mengapa tipe tidak cocok daripada menggunakan tipe casting. Sangat mungkin bahwa beberapa bug runtime bersembunyi di bawah permukaan.


Jangan berbohong. Patuhi kontrak Anda.


Tepatnya


Jenisnya adalah dokumentasi. Ketika mendokumentasikan suatu fungsi, tidakkah Anda ingin menyampaikan informasi sebanyak mungkin?


 //   function getUser(id) { /* ... */ } //     : name  age function getUser(id) { /* ... */ } //  id       id , //     : name  age. //     undefined. function getUser(id) { /* ... */ } 

Komentar untuk fungsi getUser mana yang getUser Anda sukai? Semakin banyak Anda tahu bahwa suatu fungsi kembali, semakin baik. Misalnya, mengetahui bahwa itu dapat kembali undefined , Anda dapat menulis blok if untuk memeriksa apakah objek yang fungsi dikembalikan didefinisikan sebelum meminta properti dari objek ini.


Hal yang persis sama dengan tipe: semakin akurat suatu tipe dijelaskan, semakin banyak informasi yang disampaikannya.


 function getUserType(id: number): string { /* ... */ } function getUserType(id: number): 'standard' | 'premium' | 'admin' { /* ... */ } 

Versi kedua dari fungsi getUserType jauh lebih informatif, dan karenanya pemanggil berada dalam situasi yang jauh lebih nyaman. Lebih mudah untuk memproses nilai jika Anda mungkin tahu (kontrak, ingat?) Bahwa itu akan menjadi salah satu dari tiga baris yang diberikan, dan bukan sembarang garis. Untuk memulai dengan apa yang Anda ketahui dengan pasti - nilai tidak boleh berupa string kosong.


Mari kita pertimbangkan contoh yang lebih nyata. Tipe State menjelaskan status komponen yang meminta beberapa data dari backend. Apakah tipe ini akurat?


 interface State { isLoading: boolean; data?: string[]; errorMessage?: string; } 

Klien yang menggunakan tipe ini harus menangani beberapa kombinasi nilai properti negara yang tidak biasa. Misalnya, sebuah situasi tidak mungkin ketika properti data dan errorMessage secara bersamaan didefinisikan: permintaan data dapat berhasil atau gagal.


Kami dapat membuat jenis ini jauh lebih akurat dengan bantuan jenis serikat yang didiskriminasi :


 type State = | { status: 'loading' } | { status: 'successful', data: string[] } | { status: 'failed', errorMessage: string }; 

Sekarang klien yang menggunakan tipe ini memiliki lebih banyak informasi: ia tidak perlu lagi memproses kombinasi properti yang salah.


Tepatnya. Berikan informasi sebanyak mungkin pada tipe Anda.


Mulai dengan Jenis


Karena tipe merupakan kontrak dan dokumentasi, maka sangat bagus untuk mendesain fungsi (atau metode) Anda.


Ada banyak artikel di Internet yang menyarankan programmer untuk berpikir sebelum menulis kode . Saya sepenuhnya membagikan pendekatan ini. Godaan untuk melompat langsung ke kode itu bagus, tetapi ini sering mengarah pada keputusan yang buruk. Sedikit waktu yang dihabiskan untuk memikirkan implementasi selalu terbayar dengan baik.


Jenis sangat berguna dalam proses ini. Berpikir mengarah pada penciptaan tanda tangan jenis fungsi yang terkait dengan penyelesaian masalah Anda. Dan itu hebat, karena Anda fokus pada apa fungsi Anda lakukan, daripada memikirkan bagaimana mereka melakukannya.


Bereaksi JS memiliki konsep Komponen Pesanan Tinggi (HOC). Ini adalah fungsi yang memperluas komponen yang diberikan dalam beberapa cara. Misalnya, Anda dapat membuat komponen orde lebih tinggi withLoadingIndicator yang menambahkan indikator pemuatan ke komponen yang ada.


Mari kita menulis tanda tangan jenis untuk fungsi ini. Fungsi menerima input komponen dan mengembalikan komponen juga. Untuk mewakili suatu komponen, kita dapat menggunakan tipe React ComponentType .


ComponentType adalah tipe generik yang diparameterisasi oleh tipe properti komponen. withLoadingIndicator menerima komponen dan mengembalikan komponen baru yang menampilkan komponen asli atau indikator pemuatan. Keputusan tentang apa yang akan ditampilkan dibuat berdasarkan nilai dari properti logis baru - isLoading . Dengan demikian, komponen yang dikembalikan membutuhkan properti yang sama dengan yang asli, hanya properti isLoading baru yang ditambahkan.


Kami akan menyelesaikan jenisnya. withLoadingIndicator menerima komponen tipe ComponentType<P> , di mana P menunjukkan tipe properti. withLoadingIndicator mengembalikan komponen dengan properti lanjutan tipe P & { isLoading: boolean } .


 const withLoadingIndicator = <P>(Component: ComponentType<P>) : ComponentType<P & { isLoading: boolean }> => ({ isLoading, ...props }) => { /* ... */ } 

Berhubungan dengan jenis-jenis fungsi, kami terpaksa berpikir tentang apa yang akan ada di inputnya dan apa yang akan di output. Dengan kata lain, kami harus merancang suatu fungsi . Menulis implementasinya sekarang mudah.


Mulai dengan tipe. Biarkan jenis memaksa Anda untuk merancang terlebih dahulu, dan baru kemudian menulis implementasinya.


Ambil ketegaran


Tiga perintah pertama mengharuskan Anda memberi perhatian khusus pada jenis. Untungnya, ketika menyelesaikan masalah ini, Anda tidak perlu melakukan semuanya sendiri - seringkali kompiler TypeScript akan memberi tahu Anda ketika tipe Anda berbohong atau ketika mereka tidak cukup akurat.


Anda dapat membantu kompiler melakukan ini dengan lebih baik dengan --strict flag --strict . Ini adalah meta flag yang --noImplicitAny semua opsi pengecekan tipe ketat: --noImplicitAny , --noImplicitThis , --alwaysStrict , --strictBindCallApply , --strictNullChecks , --strictFunctionTypes dan --strictPropertyInitialization .


Apa yang dilakukan bendera? Secara umum, dimasukkannya mereka menyebabkan peningkatan jumlah kesalahan kompilasi TypeScript. Dan ini bagus! Lebih banyak kesalahan kompilasi - lebih banyak bantuan dari kompiler.


Mari kita lihat bagaimana mengaktifkan flag --strictNullChecks membantu mendeteksi kesalahan pada kode.


 function getUser(id: number): User { if (id >= 0) { return { name: 'John', age: 12 }; } else { return undefined; } } 

Tipe getUser memastikan bahwa fungsi selalu mengembalikan objek tipe User . Namun, lihat implementasinya: sebuah fungsi juga dapat mengembalikan yang undefined !


Untungnya, mengaktifkan flag --strictNullChecks menghasilkan kesalahan kompilasi:


 Type 'undefined' is not assignable to type 'User'. 

Compiler TypeScript mendeteksi kepalsuan. Untuk menghilangkan kesalahan ini, cukup jujur โ€‹โ€‹untuk mengatakan yang sebenarnya:


 function getUser(id: number): User | undefined { /* ... */ } 

Terima kerasnya pengecekan tipe. Biarkan kompiler melindungi Anda dari kesalahan.


Tetap up to date


TypeScript berkembang dengan sangat cepat. Rilis baru dirilis setiap dua bulan. Setiap rilis membawa peningkatan bahasa yang signifikan dan fitur baru.


Sering terjadi bahwa fitur-fitur baru dari bahasa memungkinkan Anda untuk menentukan jenis lebih akurat dan memeriksanya lebih ketat.


Misalnya, dalam versi 2.0 Jenis Diskriminasi diperkenalkan (saya sebutkan dalam perintah, akurat ).


Versi 3.2 memperkenalkan flag compiler --strictBindCallApply , yang mencakup pengetikan yang benar untuk fungsi bind , call dan apply .


Versi 3.4 meningkatkan inferensi tipe dalam fungsi tingkat tinggi , yang membuatnya lebih mudah untuk menggunakan tipe yang tepat saat menulis kode dalam gaya fungsional.


Posisi saya adalah bahwa mengenal fitur-fitur bahasa yang diperkenalkan dalam versi terbaru dari TypeScript sebenarnya sepadan. Seringkali ini dapat membantu Anda mengikuti empat perintah lainnya dari daftar.


Titik awal yang baik adalah Roadmap TypeScript resmi . Ini juga akan menyenangkan untuk secara teratur memeriksa bagian TypeScript di Microsoft Devblog , karena semua pengumuman rilis ada di sana.


Tetap up to date dengan fitur-fitur baru bahasa ini, dan biarkan pengetahuan ini bekerja untuk Anda.


Ringkasan


Saya harap daftar ini bermanfaat. Seperti biasa dan dalam segala hal, seseorang hendaknya tidak secara membabi buta mengikuti perintah-perintah ini. Tapi saya sangat percaya bahwa aturan ini akan membuat Anda menjadi pengembang TypeScript yang lebih baik.


Saya akan senang melihat pendapat Anda tentang hal ini dalam komentar.


Bonus


Apakah Anda menyukai artikel ini tentang TypeScript? Saya yakin Anda juga akan menyukai PDF gratis ini: 10 Kesalahan pengembangan TypeScript yang membuat kode Anda tidak aman.

Source: https://habr.com/ru/post/id461565/


All Articles