Analisis statis

Analisis statis adalah jenis pengujian yang menyediakan pemeriksaan otomatis terhadap kode Anda tanpa benar-benar menjalankannya atau harus menulis pengujian otomatis. Anda kemungkinan sudah melihat pengujian semacam ini jika menggunakan IDE seperti VSCode. Pemeriksaan jenis yang dilakukan oleh TypeScript adalah jenis analisis statis yang dapat muncul sebagai baris berlekuk-lekuk di bawah error atau peringatan.

ESLint

ESLint adalah alat yang dapat memberikan masukan terkait kemungkinan masalah dalam codebase Anda. Masalah ini mungkin termasuk safe,tetapi error atau perilaku non-standar akan muncul dengan sendirinya. ESLint memungkinkan Anda menerapkan sejumlah aturan yang diperiksa pada codebase, termasuk banyak aturan dalam kumpulan "direkomendasikan".

Contoh yang baik dari aturan ESLint adalah aturan no-unsafe-finally. Hal ini mencegah Anda menulis pernyataan yang mengubah alur kontrol program di dalam blok finally. Ini adalah aturan yang bagus, karena cara ini tidak biasa untuk menulis JavaScript yang mungkin sulit diikuti. Namun, ini juga merupakan sesuatu yang harus dapat dideteksi oleh proses peninjauan kode yang efektif.

  try {
    const result = await complexFetchFromNetwork();
    if (!result.ok) {
      throw new Error("failed to fetch");
    }
  } finally {
    // warning - this will 'overrule' the previous exception!
    return false;
  }

Dengan demikian, ESLint bukanlah pengganti proses peninjauan yang baik (dan panduan gaya yang menentukan tampilan codebase Anda), karena ESLint tidak akan menangkap setiap pendekatan tidak lazim yang mungkin coba diperkenalkan oleh developer ke codebase Anda. Panduan Praktik Eng Google memiliki bagian singkat tentang "menjaganya tetap sederhana".

ESLint memungkinkan Anda melanggar aturan dan memberi anotasi pada kode sebagai "diizinkan". Misalnya, Anda dapat mengizinkan logika sebelumnya dengan memberinya anotasi sebagai berikut:

  finally {
    // eslint-disable-next-line no-unsafe-finally
    return false;
  }

Jika Anda terus-menerus melanggar aturan, pertimbangkan untuk menonaktifkannya. Alat ini mendorong Anda untuk menulis kode dengan cara tertentu, tetapi tim Anda mungkin terbiasa menulis kode dengan cara yang berbeda dan sudah menyadari risiko pendekatan tersebut.

Terakhir, mengaktifkan alat analisis statis pada codebase besar dapat menimbulkan banyak derau yang tidak membantu (dan pekerjaan yang sibuk untuk pemfaktoran ulang) daripada kode yang berfungsi dengan baik. Jadi akan lebih mudah untuk mengaktifkannya di awal siklus hidup proyek.

Plugin ESLint untuk dukungan browser

Anda dapat menambahkan plugin ke ESLint yang menandai penggunaan API yang tidak didukung secara luas, atau tidak didukung oleh daftar browser target Anda. Paket eslint-plugin-compat dapat memperingatkan Anda ketika API mungkin tidak tersedia untuk pengguna, sehingga Anda tidak perlu terus melacaknya sendiri.

Pemeriksaan jenis untuk analisis statis

Saat mempelajari JavaScript, developer baru biasanya diperkenalkan pada gagasan bahwa JavaScript adalah bahasa yang diketik dengan lemah. Artinya, variabel dapat dideklarasikan sebagai satu jenis, lalu menggunakan lokasi yang sama untuk sesuatu yang benar-benar berbeda. Ini mirip dengan Python dan bahasa skrip lainnya, tetapi tidak seperti bahasa yang dikompilasi seperti C/C++ dan Rust.

Bahasa semacam ini mungkin cocok untuk memulai—dan bisa dibilang kesederhanaan ini telah membuat JavaScript begitu populer—tetapi sering kali ini menjadi titik kegagalan untuk beberapa codebase, atau setidaknya sesuatu yang memungkinkan terjadinya error yang membingungkan. Misalnya, dengan meneruskan number yang diharapkan memiliki string atau jenis objek, nilai yang salah diketik tersebut dapat menyebar ke berbagai library sebelum akhirnya menyebabkan TypeError yang membingungkan.

TypeScript

TypeScript adalah solusi yang paling umum atas kurangnya informasi pengetikan JavaScript. Kursus ini menggunakannya secara luas. Meskipun tidak mencakup kursus tentang TypeScript, kursus ini dapat menjadi bagian penting dari toolbox Anda karena menyediakan analisis statis.

Untuk contoh singkat, kode ini yang diharapkan akan diberi callback yang menerima nama string dan usia number:

const callback = (name: string, age: string): void => {
  console.info(name, 'is now', age, 'years old!');
};
onBirthday(callback);

Menghasilkan error berikut saat dijalankan melalui TypeScript, atau bahkan saat kursor diarahkan ke IDE:

bad.ts:4:12 - error TS2345: Argument of type '(name: string, age: string) => void' is not assignable to parameter of type '(name: string, age: number) => void'.
  Types of parameters 'age' and 'age' are incompatible.
    Type 'number' is not assignable to type 'string'.

4 onBirthday(callback);
             ~~~~~~~~

Found 1 error in bad.ts:4
Kode dari contoh sebelumnya, yang ditampilkan di IDE dengan pesan error ditampilkan dalam pop-up.
VSCode yang menunjukkan bahwa Anda telah meneruskan jenis yang salah.

Pada akhirnya, tujuan penggunaan TypeScript adalah untuk mencegah error seperti ini—usia harus berupa number, bukan string—yang merayap ke dalam project Anda. Error semacam ini bisa sulit dideteksi menggunakan jenis pengujian lainnya. Selain itu, sistem jenis dapat memberikan masukan bahkan sebelum pengujian ditulis. Hal ini dapat mempermudah proses penulisan kode dengan memberi Anda masukan awal tentang error jenis saat Anda mengembangkan software, bukan saat kode akhirnya dijalankan.

Bagian paling menantang dalam menggunakan TypeScript adalah menyiapkannya dengan benar. Setiap project memerlukan file tsconfig.json, yang meskipun terutama digunakan oleh alat command line tsc, juga dibaca oleh IDE seperti VSCode bersama dengan banyak alat dan alat build lainnya, termasuk Vitest. File ini berisi ratusan opsi dan flag, dan Anda dapat menemukan beberapa referensi bagus untuk menyiapkannya di sini:

Tips TypeScript umum

Saat menyiapkan dan menggunakan TypeScript melalui file tsconfig.json, perhatikan hal berikut:

  • Pastikan file sumber Anda benar-benar disertakan dan dicentang. Jika file secara misterius "tidak memiliki error", itu mungkin karena file tersebut tidak diperiksa.
  • Mendeskripsikan jenis dan antarmuka secara eksplisit dalam file .d.ts, daripada dijelaskan secara implisit saat Anda menulis fungsi, dapat menjadikan codebase Anda lebih mudah untuk diuji. Akan lebih mudah untuk menulis tiruan dan versi 'palsu' kode jika antarmuka yang terlibat jelas. .

TypeScript implisit semua

Salah satu opsi konfigurasi TypeScript yang paling andal dan bermanfaat adalah flag noImplicitAny. Namun, pengaktifan ini juga sering kali paling sulit, terutama jika Anda sudah memiliki codebase yang besar. (Tanda noImplicitAny diaktifkan secara default jika Anda berada dalam mode strict, tetapi tidak dalam mode lain.)

Flag ini akan membuat fungsi ini menampilkan error:

export function fibonacci(n) {
  if (n <= 1) {
    return 0;
  } else if (n === 2) {
    return 1;
  }
  return fibonacci(n - 1) + fibonacci(n - 2);
}

Meskipun, sebagai pembaca, cukup jelas bahwa n harus berupa angka, TypeScript tidak dapat mengonfirmasi hal ini dengan yakin. Jika Anda menggunakan VSCode, mengarahkan kursor ke fungsi tersebut akan mendeskripsikannya sebagai berikut:

function fibonacci(n: any): any

Pemanggil fungsi ini akan dapat meneruskan nilai jenis any (jenis yang memungkinkan jenis lainnya), bukan hanya number. Dengan mengaktifkan flag noImplicitAny, Anda dapat mengamankan jenis kode ini selama pengembangan, tanpa perlu menulis pengujian logika bisnis yang ekstensif untuk kode Anda yang meneruskan jenis data yang salah di tempat tertentu.

Perbaikan sederhana di sini adalah menandai argumen n dan jenis nilai yang ditampilkan fibonacci sebagai number.

Flag noImplicitAny tidak mencegah Anda secara eksplisit menulis any di codebase. Anda masih dapat menulis fungsi yang menerima atau menampilkan jenis any. Itu hanya memastikan bahwa Anda memberikan jenis pada setiap variabel.