Komentar #

Komentar adalah salah satu alat komunikasi paling penting dalam kode — bukan komunikasi dengan compiler, tapi komunikasi dengan manusia: rekan tim, reviewer, dan dirimu sendiri enam bulan ke depan. TypeScript mewarisi semua sintaks komentar dari JavaScript, tapi menambahkan satu lapisan yang jauh lebih powerful: JSDoc. Dengan JSDoc, komentar bukan lagi teks pasif yang diabaikan compiler — ia menjadi sumber informasi tipe dan dokumentasi yang bisa dibaca oleh IDE, tools dokumentasi, dan bahkan TypeScript compiler itu sendiri. Artikel ini membahas semua jenis komentar di TypeScript, kapan menggunakannya, dan yang sama pentingnya — kapan tidak menggunakannya.

Komentar Satu Baris (//) #

Komentar satu baris adalah bentuk paling sederhana. Semua teks setelah // hingga akhir baris diabaikan oleh compiler. Ini cocok untuk catatan singkat yang menjelaskan mengapa sesuatu dilakukan, bukan apa yang dilakukan — karena kode yang baik sudah cukup menjelaskan “apa”-nya sendiri.

let batasPercobaan: number = 3;        // Batas sesuai kebijakan keamanan
let intervalKadaluarsa: number = 3600; // Dalam detik — 1 jam

// Mulai hitung dari 1, bukan 0, agar pesan error lebih natural untuk pengguna
for (let percobaan = 1; percobaan <= batasPercobaan; percobaan++) {
  console.log(`Percobaan ${percobaan} dari ${batasPercobaan}`);
}

Apa yang Layak Dikomentari #

Komentar satu baris paling bermanfaat untuk menjelaskan keputusan yang tidak terlihat dari kode itu sendiri:

// ANTI-PATTERN: Komentar yang hanya mengulang kode — tidak menambah informasi
const usia: number = 17; // Tetapkan usia ke 17
if (usia >= 18) {        // Periksa apakah usia lebih dari atau sama dengan 18
  console.log("Dewasa"); // Cetak "Dewasa"
}

// BENAR: Komentar yang menjelaskan alasan (the "why"), bukan aksi (the "what")
const usia: number = 17;
if (usia >= 18) {
  // Sesuai UU No. 35 Tahun 2014 — batas dewasa adalah 18 tahun
  console.log("Akses penuh diizinkan");
}

Komentar Multi-Baris (/* ... */) #

Komentar multi-baris mengapit blok teks di antara /* dan */. Gunakan ini ketika penjelasan tidak cukup dalam satu baris, atau saat kamu ingin menonaktifkan sementara blok kode yang besar.

/*
  Algoritma ini menggunakan pendekatan sliding window untuk menghitung
  rata-rata bergerak. Kompleksitas waktu O(n), jauh lebih efisien dari
  pendekatan naive O(n²) yang menghitung ulang dari awal setiap iterasi.

  Referensi: https://en.wikipedia.org/wiki/Moving_average
*/
function rataRataBergerak(data: number[], ukuranWindow: number): number[] {
  const hasil: number[] = [];
  let jumlah = 0;

  for (let i = 0; i < data.length; i++) {
    jumlah += data[i];

    if (i >= ukuranWindow) {
      jumlah -= data[i - ukuranWindow];
    }

    if (i >= ukuranWindow - 1) {
      hasil.push(jumlah / ukuranWindow);
    }
  }

  return hasil;
}

Menonaktifkan Kode Sementara #

Komentar multi-baris juga sering digunakan saat debugging untuk menonaktifkan sementara blok kode:

function prosesData(input: string[]): string[] {
  const hasil = input.map((item) => item.trim().toLowerCase());

  /*
  // Normalisasi tambahan — dinonaktifkan sementara untuk investigasi bug #4521
  const hasilNormalisasi = hasil.map((item) => {
    return item.replace(/[^a-z0-9]/g, "-");
  });
  return hasilNormalisasi;
  */

  return hasil;
}
Kode yang dikomentari dalam jangka panjang adalah code smell — ia menciptakan kebingungan apakah kode tersebut masih relevan atau sudah aman dihapus. Jika kamu menonaktifkan kode untuk debugging, hapus komentar tersebut sebelum di-commit. Untuk menyimpan versi lama kode, gunakan version control (Git), bukan komentar.

Komentar JSDoc (/** ... */) #

JSDoc adalah bentuk komentar paling powerful di TypeScript. Ia bukan sekadar teks — ia adalah metadata terstruktur yang dibaca oleh IDE (untuk tooltip dan autocomplete), tools seperti TypeDoc (untuk menghasilkan dokumentasi HTML), dan dalam beberapa kasus, TypeScript compiler sendiri. JSDoc dimulai dengan /** (dua bintang) dan diakhiri dengan */.

/**
 * Menghitung total harga setelah diskon dan pajak diterapkan.
 *
 * @param harga - Harga dasar produk dalam Rupiah
 * @param diskon - Persentase diskon (0–100). Default: 0
 * @param pajakPersen - Persentase pajak (0–100). Default: 11 (PPN)
 * @returns Total harga akhir setelah diskon dan pajak
 *
 * @example
 * ```typescript
 * hitungTotal(100000, 10, 11); // 99900 (diskon 10%, PPN 11%)
 * hitungTotal(50000);          // 55500 (tanpa diskon, PPN 11%)
 * ```
 */
function hitungTotal(
  harga: number,
  diskon: number = 0,
  pajakPersen: number = 11
): number {
  const setelahDiskon = harga * (1 - diskon / 100);
  const setelahPajak = setelahDiskon * (1 + pajakPersen / 100);
  return Math.round(setelahPajak);
}

Saat kamu mengarahkan kursor ke nama fungsi hitungTotal di IDE seperti VS Code, seluruh JSDoc ditampilkan sebagai tooltip — termasuk deskripsi parameter, return value, dan contoh penggunaan.

JSDoc untuk Interface dan Type #

JSDoc sangat berguna untuk mendokumentasikan interface dan type agar setiap properti memiliki penjelasan yang muncul di IDE:

/**
 * Representasi data produk dalam sistem e-commerce.
 * Digunakan untuk response API dan state di frontend.
 */
interface Produk {
  /** ID unik produk — format UUID v4 */
  id: string;

  /** Nama produk yang ditampilkan ke pengguna */
  nama: string;

  /** Harga dalam satuan Rupiah (IDR), bukan sen */
  harga: number;

  /** Jumlah stok yang tersedia. 0 berarti habis, -1 berarti tidak dilacak */
  stok: number;

  /** Kategori produk. Gunakan nilai dari enum KategoriProduk */
  kategori: string;

  /** Timestamp pembuatan dalam format ISO 8601 */
  dibuatPada: string;

  /** URL gambar utama produk. Opsional — bisa null jika belum ada gambar */
  gambarUrl?: string | null;
}

JSDoc untuk Class #

/**
 * Service untuk mengelola autentikasi pengguna.
 *
 * @remarks
 * Semua token disimpan di memory, bukan localStorage, untuk mencegah
 * serangan XSS. Token di-refresh otomatis 5 menit sebelum kadaluarsa.
 *
 * @example
 * ```typescript
 * const auth = new AuthService("https://api.example.com");
 * const token = await auth.masuk("[email protected]", "password");
 * ```
 */
class AuthService {
  private baseUrl: string;
  private tokenAktif: string | null = null;

  /**
   * Membuat instance AuthService baru.
   * @param baseUrl - Base URL API autentikasi (tanpa trailing slash)
   */
  constructor(baseUrl: string) {
    this.baseUrl = baseUrl;
  }

  /**
   * Melakukan autentikasi pengguna dan menyimpan token.
   *
   * @param email - Alamat email pengguna
   * @param password - Password pengguna (dikirim via HTTPS, tidak di-log)
   * @returns Token JWT jika berhasil
   * @throws {Error} Jika kredensial salah atau server tidak dapat dijangkau
   */
  async masuk(email: string, password: string): Promise<string> {
    const response = await fetch(`${this.baseUrl}/auth/login`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email, password }),
    });

    if (!response.ok) {
      throw new Error(`Autentikasi gagal: ${response.status}`);
    }

    const data = await response.json();
    this.tokenAktif = data.token;
    return data.token;
  }
}

Tag JSDoc yang Umum Digunakan #

TagKegunaanContoh
@paramMendokumentasikan parameter@param nama - Nama pengguna
@returnsMendokumentasikan nilai kembalian@returns Token JWT
@throwsException yang mungkin dilempar@throws {Error} Jika tidak valid
@exampleContoh penggunaan dengan kode@example + blok kode
@deprecatedMenandai API yang sudah usang@deprecated Gunakan fungsiV2()
@seeReferensi ke dokumentasi lain@see https://docs.example.com
@remarksCatatan tambahan panjang@remarks Perhatian khusus...
@sinceVersi pertama tersedia@since v2.1.0
@internalHanya untuk penggunaan internalTidak tampil di dok publik

Direktif Komentar TypeScript #

TypeScript mengenal beberapa komentar khusus yang bukan sekadar dokumentasi, tapi memberi instruksi langsung ke compiler. Ini adalah kategori komentar yang paling berbahaya jika disalahgunakan.

@ts-ignore — Abaikan Error Satu Baris #

@ts-ignore memerintahkan compiler untuk mengabaikan error TypeScript pada baris berikutnya:

// @ts-ignore
const nilai: number = "ini bukan angka"; // Error biasanya muncul, tapi diabaikan

@ts-expect-error — Harapkan Error (Lebih Aman) #

@ts-expect-error adalah versi yang lebih aman dari @ts-ignore. Perbedaan krusialnya: jika baris berikutnya tidak menghasilkan error, TypeScript justru melaporkan error pada direktif itu sendiri. Ini memaksa kamu menghapus direktif saat kode sudah diperbaiki.

// ANTI-PATTERN: @ts-ignore diam-diam — tidak ada peringatan jika error sudah diperbaiki
// @ts-ignore
fungsiYangSudahDiperbaiki(argumenBenar); // Jika sudah benar, @ts-ignore "nganggur" tanpa peringatan

// BENAR: @ts-expect-error — compiler komplain jika error tidak terjadi
// @ts-expect-error: Sengaja tes dengan tipe yang salah untuk validasi runtime error handling
fungsiDenganValidasi("bukan-angka");

Tabel perbandingan keduanya:

Aspek@ts-ignore@ts-expect-error
Mengabaikan error✓ Ya✓ Ya
Error jika tidak ada error✗ Tidak✓ Ya
Cocok untukLegacy code daruratTest dan intentional suppression
RisikoTinggi — bisa menyembunyikan bugRendah — self-cleaning

@ts-nocheck — Nonaktifkan Seluruh File #

@ts-nocheck di baris pertama file menonaktifkan semua type checking untuk seluruh file tersebut:

// @ts-nocheck
// File ini adalah migrasi dari JavaScript — type checking dinonaktifkan sementara
// TODO: Hapus @ts-nocheck setelah migrasi selesai (target: Sprint 24)

const data = ambilData();
prosesData(data.apapun.tanpa.tipe);
@ts-nocheck adalah sinyal bahwa ada masalah besar yang ditunda, bukan diselesaikan. Jika kamu menemukan @ts-nocheck di codebase tanpa komentar TODO yang jelas, tanya kenapa ia ada di sana. Jangan tambahkan @ts-nocheck baru ke file yang sudah punya type coverage — itu mundur satu langkah.

@ts-check — Aktifkan Type Checking di File .js #

Kebalikan dari @ts-nocheck, direktif ini mengaktifkan type checking TypeScript di file JavaScript biasa — tanpa perlu mengubah ekstensi file:

// @ts-check
// File JavaScript biasa, tapi mendapat type checking dari TypeScript

/**
 * @param {string} nama
 * @param {number} usia
 * @returns {string}
 */
function buatBio(nama, usia) {
  return `${nama}, ${usia} tahun`;
}

buatBio("Budi", 25); // ✓
// buatBio(123, "dua puluh lima"); // ✗ TypeScript akan melaporkan error

Ini sangat berguna saat migrasi bertahap dari JavaScript ke TypeScript — kamu bisa menambahkan type checking per file tanpa harus mengkonversi semuanya sekaligus.


Alur Penggunaan Direktif Komentar #

Berikut panduan kapan menggunakan masing-masing direktif:

flowchart TD
    A{Ada error TypeScript yang\ningin kamu abaikan?} -- Tidak --> B[Jangan tambahkan direktif apapun]
    A -- Ya --> C{Error ini memang\ndisengaja untuk testing?}
    C -- Ya --> D[Gunakan @ts-expect-error\ndengan penjelasan alasan]
    C -- Tidak --> E{Error dari library pihak ketiga\nyang tidak bisa diubah?}
    E -- Ya --> F[Gunakan @ts-ignore\ndengan komentar penjelasan]
    E -- Tidak --> G{Seluruh file adalah\nmigrasi dari JavaScript?}
    G -- Ya --> H[Gunakan @ts-nocheck\ndengan TODO deadline]
    G -- Tidak --> I[Perbaiki kode — jangan\nsuppress error yang bisa diperbaiki]

    style B fill:#51cf66,color:#fff
    style D fill:#339af0,color:#fff
    style F fill:#fcc419,color:#000
    style H fill:#ff922b,color:#fff
    style I fill:#51cf66,color:#fff

Praktik Terbaik Menulis Komentar #

Komentari “Mengapa”, Bukan “Apa” #

Kode yang ditulis dengan baik sudah menjelaskan apa yang dilakukannya. Komentar yang baik menjelaskan mengapa keputusan tersebut diambil — informasi yang tidak bisa dilihat dari kode itu sendiri.

// ANTI-PATTERN: Komentar yang menjelaskan "apa" — redundan dengan kode
// Iterasi array dan tambahkan setiap item ke hasil
const hasil = items.map((item) => item.harga * item.kuantitas);

// BENAR: Komentar yang menjelaskan "mengapa" — menambah konteks
// Harga dikalikan kuantitas di sini (bukan di model) agar kalkulasi
// bisa dioverride per transaksi tanpa mengubah data produk
const hasil = items.map((item) => item.harga * item.kuantitas);

Komentar TODO dan FIXME #

Gunakan prefiks standar agar mudah dicari dengan grep atau fitur IDE:

// TODO: Tambahkan validasi email format sebelum Sprint 15
// FIXME: Race condition di sini jika dua request masuk bersamaan — lihat issue #892
// HACK: Workaround untuk bug di library axios v1.2.3, hapus setelah upgrade
// NOTE: Fungsi ini dipanggil di 47 tempat — perubahan tanda tangan butuh migration
// PERF: Bisa dioptimasi dengan memoization jika jadi bottleneck di profiling

Jangan Duplikasi Informasi yang Ada di Tipe #

TypeScript sudah punya sistem tipe yang ekspresif. Komentar yang menduplikasi informasi tipe hanya menambah noise dan bisa jadi salah setelah refactoring:

// ANTI-PATTERN: Komentar yang menduplikasi tipe — akan basi setelah refactoring
/**
 * @param pengguna - Object pengguna dengan properti nama (string) dan usia (number)
 * @returns string
 */
function formatPengguna(pengguna: { nama: string; usia: number }): string {
  return `${pengguna.nama} (${pengguna.usia})`;
}

// BENAR: Komentar fokus pada konteks bisnis, bukan ulang tipe
/**
 * Memformat data pengguna untuk ditampilkan di header profil.
 * Format: "Nama (Usia)" — sesuai desain Figma v3 halaman profil.
 */
function formatPengguna(pengguna: { nama: string; usia: number }): string {
  return `${pengguna.nama} (${pengguna.usia})`;
}

Menghasilkan Dokumentasi dari JSDoc #

Salah satu manfaat terbesar JSDoc adalah kemampuannya menghasilkan dokumentasi HTML otomatis. Tool yang paling populer untuk TypeScript adalah TypeDoc:

# Install TypeDoc
npm install --save-dev typedoc

# Generate dokumentasi
npx typedoc src/index.ts --out docs/

# Atau konfigurasi via typedoc.json
{
  "entryPoints": ["src/index.ts"],
  "out": "docs",
  "excludePrivate": true,
  "excludeInternal": true,
  "theme": "default"
}

Dengan konfigurasi ini, setiap komentar JSDoc yang kamu tulis akan muncul sebagai halaman dokumentasi yang rapi — lengkap dengan navigasi, search, dan link antar tipe.


Ringkasan #

  • Komentar satu baris (//) — gunakan untuk catatan singkat yang menjelaskan mengapa, bukan apa; kode yang baik sudah berbicara sendiri tentang apa yang dilakukan.
  • Komentar multi-baris (/* */) — gunakan untuk penjelasan algoritma, keputusan arsitektur, atau menonaktifkan kode sementara; tapi hapus kode yang dikomentari sebelum commit ke repository.
  • JSDoc (/** */) — wajib untuk semua fungsi publik, interface, dan class; JSDoc bukan sekadar komentar — ia adalah dokumentasi yang dibaca IDE, TypeDoc, dan pengguna library kamu.
  • @ts-expect-error lebih aman dari @ts-ignore — gunakan @ts-expect-error untuk intentional suppression karena compiler akan complain jika error-nya hilang, memaksamu membersihkan direktif yang tidak lagi diperlukan.
  • @ts-nocheck adalah tanda bahaya — jika kamu menambahkannya, sertakan komentar TODO dengan deadline kapan akan dihapus.
  • @ts-check di file .js** — cara mudah menambahkan type checking bertahap tanpa mengubah ekstensi file, ideal untuk migrasi dari JavaScript.
  • Hindari duplikasi tipe di komentar — jangan jelaskan tipe di komentar jika informasinya sudah ada di anotasi TypeScript; fokus komentar pada konteks bisnis dan keputusan yang tidak terlihat dari kode.
  • Prefiks standar untuk action item — gunakan TODO, FIXME, HACK, NOTE, PERF secara konsisten agar mudah dicari di seluruh codebase.

← Sebelumnya: Sintaks Utama   Berikutnya: Variabel →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact