Pengantar TypeScript
Diterbitkan: 2020-10-29Bahasa pertama yang pernah saya gunakan adalah C dan Java. Dengan bahasa ini, setiap kali Anda mendefinisikan variabel, Anda harus menentukan tipenya. Jika Anda mencoba untuk menetapkan nilai tipe lain, kompiler akan mengeluh:
// main.c int main() { int x = "two"; return 0; } > cc main.c -o main // warning: initialization makes integer from pointer without a castMasalahnya adalah, karena kurangnya pengalaman saya, banyak keluhan yang saya terima dari kompiler tampak samar dan rumit. Itu sebabnya, pada akhirnya, saya melihat compiler sebagai alat yang membatasi kreativitas saya, padahal pada kenyataannya itu seharusnya menjadi mitra yang ada untuk membantu.

Kemudian dalam karir saya, saya mulai menggunakan beberapa bahasa pemrograman tanpa pengetikan yang kuat, seperti JavaScript atau PHP. Saya pikir mereka cukup keren: sangat mudah untuk membuat prototipe dengan cepat tanpa harus berurusan dengan kompiler yang pilih-pilih.
Seperti yang sudah Anda ketahui, bahasa pemrograman yang menjadi dasar WordPress adalah PHP dan JavaScript. Ini berarti Anda mungkin terbiasa mengkodekan plugin dan tema Anda tanpa kompiler yang mengawasi Anda. Hanya Anda, keterampilan, dan kreativitas Anda. Nah, dan kesalahan seperti ini:
const user = getUser( userId ); greet( user.name ); // Uncaught TypeError: user is undefined Jika Anda muak dengan bug seperti yang undefined dalam kode Anda, inilah saatnya untuk menambahkan kompiler ke alur kerja Anda. Mari kita lihat apa itu TypeScript dan bagaimana hal itu memungkinkan kita untuk meningkatkan kualitas perangkat lunak kita dengan beberapa kali lipat.
Apa itu TypeScript
TypeScript adalah bahasa pemrograman berbasis JavaScript yang dibuat dengan tujuan untuk menambahkan pengetikan yang kuat dan statis. Tipe TypeScript memungkinkan kita untuk mendeskripsikan bentuk objek dan variabel kita, menghasilkan kode yang terdokumentasi dengan lebih baik dan lebih kuat. TypeScript sendiri akan bertanggung jawab untuk memvalidasi semua yang kita lakukan.
Seperti yang dirancang, TypeScript adalah superset dari JavaScript. Ini berarti bahwa kode apa pun yang ditulis dalam JavaScript biasa, menurut definisi, juga TypeScript yang valid. Tetapi kebalikannya tidak benar: jika Anda menggunakan fitur khusus TypeScript, kode yang dihasilkan bukan JavaScript yang valid sampai Anda mengubahnya.
Cara Kerja TypeScript
Untuk memahami cara kerja TypeScript, kita akan menggunakan Playground , editor kecil tempat kita dapat menulis kode TypeScript dan melihat apa yang dikatakan kompiler tentangnya.
Menjadi superset dari JavaScript, menulis kode TypeScript sangat mudah. Pada dasarnya kode JavaScript berikut:
let user = "David"; let age = 34; let worksAtNelio = true; console.log( user, age, worksAtNelio );juga merupakan kode TypeScript. Anda dapat menyalin dan menempelkannya di TypeScript Playground dan Anda akan melihatnya dikompilasi. Jadi apa yang spesial darinya? Jenisnya tentu saja. Dalam JavaScript, Anda dapat melakukan hal berikut:
let user = "David"; let age = 34; let worksAtNelio = true; user = { name: "Ruth" }; console.log( user, age, worksAtNelio );tapi itu akan memicu kesalahan dalam TypeScript. Coba saja di Playground dan Anda akan melihat kesalahan berikut:
Type '{ name: string; }' is not assignable to type 'string'.Jadi apa itu semua?
TypeScript dapat menyimpulkan jenis variabel secara otomatis. Itu berarti kita tidak perlu secara eksplisit mengatakannya "hei, variabel ini adalah string" (atau angka, atau boolean, atau apa pun); sebagai gantinya, ia melihat nilai yang pertama kali diberikan dan menyimpulkan tipenya berdasarkan itu.

Dalam contoh kita, ketika kita mendefinisikan variabel user kita menetapkannya sebagai string teks "David" , jadi TypeScript mengetahui bahwa user adalah (dan harus selalu) sebuah string . Masalahnya adalah beberapa saat kemudian kami mencoba mengubah tipe variabel user kami dengan menetapkannya sebagai objek yang memiliki satu properti ( name ) yang nilainya adalah string "Ruth" . Jelas, objek ini bukan string , jadi TypeScript mengeluh dan memberi tahu kita bahwa tugas tidak dapat dilakukan.
Ada dua kemungkinan rute untuk memperbaikinya:
// Option 1 let user = "David"; user = "Ruth"; // OK. // Option 2 let user = { name: "David" }; user = { name: "Ruth" };Mari kita menjadi eksplisit ketika mendefinisikan jenis variabel kita
Tetapi inferensi tipe hanya ada untuk membantu kami. Jika kita mau, kita dapat secara eksplisit memberi tahu TypeScript tipe variabel:
let user: string = "David"; let age: number = 34; let worksAtNelio: boolean = true; console.log( user, age, worksAtNelio );yang membuat hasil yang sama persis dengan tipe yang disimpulkan oleh TypeScript. Sekarang ini menimbulkan pertanyaan: jika TypeScript dapat menyimpulkan tipe secara otomatis, mengapa kita memerlukan fitur ini?
Di satu sisi, menentukan tipe secara eksplisit dapat berfungsi untuk mendokumentasikan kode kita dengan lebih baik (yang akan menjadi lebih jelas di bagian berikutnya). Di sisi lain, ini memungkinkan kita untuk memecahkan keterbatasan sistem inferensi tipe. Yup, Anda membacanya dengan benar: ada kasus di mana inferensinya tidak terlalu bagus dan TypeScript terbaik yang dapat dilakukan adalah memberi tahu kita bahwa “well, saya tidak tahu persis variabel ini seharusnya; Saya kira itu bisa apa saja! ”
Perhatikan contoh berikut:
const getName = ( person ) => person.name; let david = { name: "David", age: 34 }; console.log( getName( david ) ); // Parameter 'person' implicitly has an 'any' type. Dalam hal ini, kami mendefinisikan fungsi getName yang menerima parameter dan mengembalikan nilai. Perhatikan berapa banyak hal yang kita asumsikan dalam fungsi yang begitu sederhana: kita mengharapkan sebuah objek ( person ) dengan setidaknya satu properti bernama name . Tetapi kami tidak benar-benar memiliki jaminan bahwa siapa pun yang memanggil fungsi ini akan menggunakannya dengan benar. Tetapi bahkan jika mereka melakukannya, kami masih tidak tahu apa jenis hasil dari fungsi ini. Tentu, Anda mungkin berasumsi bahwa nama akan menjadi string , tetapi Anda hanya tahu itu karena Anda manusia dan Anda memahami arti kata itu. Tapi lihat contoh berikut:

getName( "Hola" ); // Error getName( {} ); // Returns undefined getName( { name: "David" } ); // Returns a string getName( { name: true } ); // Returns a booleansetiap kali kita memanggil fungsi, kita mendapatkan hasil yang berbeda! Jadi, meskipun TypeScript mengawasi kami, kami masih mengalami masalah JavaScript klasik: fungsi ini dapat menerima apa saja dan dapat mengembalikan apa saja.

Solusinya, Anda dapat menebaknya, adalah dengan membubuhi keterangan fungsi secara eksplisit.
Tentukan tipe Anda sendiri
Namun sebelum kita melakukannya, mari kita lihat fitur TypeScript tambahan lainnya: tipe data khusus. Sejauh ini, hampir semua contoh kita menggunakan tipe dasar seperti string , number , boolean , dll, yang menurut saya cukup mudah dipahami. Kami juga telah melihat struktur data yang lebih kompleks, seperti objek:
let david = { name: "David", age: 34 };tapi kami tidak terlalu memperhatikan tipenya seperti yang disimpulkan oleh TypeScript, bukan? Semua yang kami lihat adalah contoh tugas yang tidak valid karena kesalahan pengetikan:
let user = "David"; user = { name: "Ruth" }; // Type '{ name: string; }' is not assignable to type 'string'.yang entah bagaimana mengisyaratkan bahwa jenis objeknya adalah " {name:string;} ," yang dapat Anda baca sebagai "ini adalah objek dengan properti yang disebut name of type string ." Jika begitulah cara tipe objek didefinisikan, maka TypeScript berikut harus valid:
let david: { name: string, age: number } = { name: "David", age: 34 };dan memang demikian. Tapi saya yakin Anda akan setuju itu sama sekali tidak nyaman. Untungnya, kita dapat membuat tipe baru di TypeScript.
Secara umum, tipe kustom pada dasarnya adalah tipe TypeScript biasa dengan nama kustom:
type Person = { name: string; age: number; }; let david: Person = { name: "David", age: 34 }; Keren, ya? Sekarang kita memiliki tipe Person , kita dapat dengan mudah membubuhi keterangan pada fungsi getName kita dan dengan jelas menentukan tipe parameter input kita:
const getName = ( person: Person ) => person.name; Dan pembaruan sederhana ini memberi TypeScript banyak informasi! Misalnya, sekarang dapat disimpulkan bahwa tipe hasil dari fungsi ini adalah string , karena ia mengetahui dengan pasti bahwa atribut name dari objek Person juga string :
let david: Person = { name: "David", age: 34 }; let davidName = getName( david ); davidName = 2; // Type 'number' is not assignable to type 'string'.Namun, seperti biasa, Anda dapat secara eksplisit membubuhi keterangan jenis hasil jika Anda ingin:
const getName = ( person: Person ): string => person.name;Lebih banyak barang dengan tipe TypeScript…
Akhirnya, saya ingin berbagi dengan Anda beberapa prestasi menarik yang dapat Anda manfaatkan jika Anda menentukan tipe Anda sendiri di TypeScript.
TypeScript sangat menuntut dalam hal menetapkan nilai ke variabel. Jika Anda telah secara eksplisit mendefinisikan jenis variabel tertentu, Anda hanya dapat menetapkan nilai yang sama persis dengan jenis itu. Mari kita lihat dengan beberapa contoh:
type Person = { name: string; age: number; }; let david: Person = { name: "David", age: 34 }; // OK let ruth: Person = { name: "Ruth" }; // Property 'age' is missing in type '{ name: string; }' but required in type 'Person' let toni: Person = { name: "Toni", age: 35, gender: "M" }; // Type '{ name: string; age: number; gender: string; }' is not assignable to type 'Person'. Object literal may only specify known properties, and 'gender' does not exist in type 'Person'. Seperti yang Anda lihat, variabel Person hanya menerima objek yang sepenuhnya sesuai dengan tipe Person . Jika beberapa atribut hilang ( ruth tidak memiliki age ) atau ada lebih banyak atribut daripada yang termasuk dalam jenis ( toni memiliki gender ), TypeScript akan mengeluh dan memicu kesalahan ketidakcocokan jenis.
Tetapi, jika kita berbicara tentang menjalankan fungsi, semuanya berbeda! Jenis argumen dalam suatu fungsi bukanlah persyaratan yang tepat, tetapi tentukan antarmuka minimum yang harus dipatuhi oleh parameter. Aku tahu, aku tahu, itu terlalu abstrak. Mari kita lihat contoh berikut, yang saya yakini akan membuat segalanya lebih jelas:
type NamedObject = { name: string; }; const getName = ( obj: NamedObject ): string => obj.name; const ruth = { name: "Ruth" } getName( ruth ); // OK const david = { name: "David", age: 34 }; getName( david ); // OK const toni = { firstName: "Toni" }; getName( toni ); // Argument of type '{ firstName: string; }' is not assignable to parameter of type 'NamedObject'. Property 'name' is missing in type '{ firstName: string; }' but required in type 'NamedObject'. Seperti yang Anda lihat, kami telah mendefinisikan ulang fungsi getName sebagai sesuatu yang sedikit lebih umum: sekarang dibutuhkan objek NamedObject , yaitu objek yang harus memiliki atribut bernama name of type string . Dengan menggunakan definisi ini, kita melihat bagaimana ruth dan david sangat cocok dengan persyaratan ini (keduanya memiliki atribut name ), tetapi toni tidak, karena tidak memiliki atribut expecte name .
Kesimpulan
TypeScript adalah bahasa pemrograman yang memperluas JavaScript dengan menambahkan definisi tipe statis. Hal ini memungkinkan kami untuk menjadi jauh lebih tepat saat mendefinisikan data yang kami kerjakan dan, yang lebih penting, ini membantu kami mendeteksi kesalahan lebih awal.
Biaya pengintegrasian TypeScript ke dalam tumpukan pengembangan relatif kecil dan dapat dilakukan secara bertahap. Karena semua kode JavaScript, menurut definisi, TypeScript, beralih dari JavaScript ke TypeScript adalah otomatis – Anda dapat menambahkan jenis dan memperindah kode Anda selangkah demi selangkah.
Jika Anda menyukai posting ini dan ingin tahu lebih banyak, silakan bagikan dan beri tahu saya di bagian komentar di bawah.
Gambar Unggulan oleh King's Church International di Unsplash.
