TypeScript dengan React — React

JavaScript dynamic typing kasih kebebasan, tapi juga sumber bug runtime. Fungsi terima string, dipanggil dengan number — gak ada yang protes sampai user klik…

TypeScript adalah JavaScript yang diberi type: keterangan jenis data, misalnya teks, angka, atau fungsi, yang dicek sebelum kodenya dijalankan. Di React, file-nya berakhiran .tsx, dan yang paling sering diberi type adalah props, state, dan event. Bayangin formulir pendaftaran yang kolomnya sudah ditentukan: "Nama (teks)" dan "Umur (angka)". Kalau kamu menulis "tujuh belas" di kolom umur, petugas loket menolaknya sebelum formulirnya diproses. TypeScript adalah petugas loket itu: dia menolak di editor, sebelum aplikasinya jalan di browser.

🧪 Tebakan cepat: ProfileCard minta umur berupa angka, tapi kamu menulis <ProfileCard nama="Budi" umur="17" /> lalu tetap menjalankan npm run dev. Apa yang tampil di browser: error merah, halaman kosong, atau "17 tahun"? Tebak dulu, jawabannya ada di bagian "Type hilang waktu dijalankan".

Props: tulis bentuknya sekali

type ProfileCardProps = {
  nama: string
  umur: number
  isAdmin?: boolean // ? artinya boleh gak dikirim
  onSapa?: () => void // fungsi tanpa argumen yang gak mengembalikan apa-apa
}

function ProfileCard({ nama, umur, isAdmin = false, onSapa }: ProfileCardProps) {
  return (
    <div onClick={onSapa}>
      <h2 id="name">{nama}</h2>
      <p id="age">{umur} tahun</p>
      {isAdmin && <span>admin</span>}
    </div>
  )
}

<ProfileCard nama="Budi" umur={17} />

Setiap kali komponen ini dipakai, TypeScript mencocokkan props yang dikirim dengan bentuk tadi. Ini yang dia bilang untuk empat pemakaian:

Kode Kata TypeScript
<ProfileCard nama="Budi" umur={17} /> aman, gak ada error
<ProfileCard nama="Budi" umur="17" /> Type 'string' is not assignable to type 'number'. (ts 2322)
<ProfileCard nama="Budi" /> Property 'umur' is missing in type '{ nama: string; }' but required in type 'ProfileCardProps'. (ts 2741)
<ProfileCard nama="Budi" umur={17} kota="Bandung" /> Property 'kota' does not exist on type 'IntrinsicAttributes & ProfileCardProps'. (penjelasan di bawah ts 2322)

Error-nya muncul sebagai garis merah tepat di prop yang salah, jadi kamu tahu letaknya sebelum membuka browser.

State: biarkan ditebak, kecuali mulai dari null

type User = { nama: string }

const [count, setCount] = useState(0) // count: number
const [user, setUser] = useState<User | null>(null) // user: User | null
const [items, setItems] = useState<string[]>([]) // items: string[]

Event: pakai type milik React

function FormNama() {
  const [nama, setNama] = useState("")

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setNama(e.target.value) // e.target adalah <input>, jadi .value pasti ada
  }

  return <input value={nama} onChange={handleChange} />
}

children: React.ReactNode

type CardProps = {
  judul: string
  children: React.ReactNode // teks, angka, JSX, array, null: semua yang bisa dirender
}

React.ReactNode adalah type paling longgar untuk isi di antara tag pembuka dan penutup, jadi <Card judul="Profil"><p>Halo</p></Card> aman.

Type hilang waktu dijalankan

Browser gak mengerti type. Sebelum dijalankan, semua type dihapus. Ini sisa ProfileCard tadi:

function ProfileCard({ nama, umur, isAdmin = false, onSapa }) {
  return (
    <div onClick={onSapa}>
      <h2 id="name">{nama}</h2>
      <p id="age">{umur} tahun</p>
      {isAdmin && <span>admin</span>}
    </div>
  )
}

type ProfileCardProps hilang seluruhnya, dan : ProfileCardProps juga. Waktu npm run dev, Vite cuma menghapus type tanpa mengeceknya, jadi umur="17" tetap tampil "17 tahun". Itu jawaban tebakannya: tampil normal, padahal TypeScript sudah protes. Yang mengecek adalah editor (garis merah) dan perintah tsc, yang di template Vite ikut jalan di npm run build ("build": "tsc -b && vite build"), jadi build-nya gagal sampai error-nya dibereskan. Data yang datang saat aplikasi jalan, misalnya hasil fetch, juga gak dicek oleh TypeScript.

⚠️ Jebakan yang sering ketemu

TL;DR: TypeScript mengecek type di editor sebelum kode jalan. Tulis bentuk props sekali dengan type (atau interface): string, number, ? untuk opsional, () => void untuk fungsi yang gak mengembalikan apa-apa, React.ReactNode untuk children. State ditebak dari nilai awal, kecuali mulai dari null atau []: tulis useState<User | null>(null) dan useState<string[]>([]). Event pakai type React: React.ChangeEvent<HTMLInputElement> untuk onChange, React.MouseEvent<HTMLButtonElement> untuk onClick, React.SubmitEvent<HTMLFormElement> untuk onSubmit. Semua type dihapus sebelum jalan, jadi error type ditangkap editor dan tsc, bukan browser.

Yang akan kamu pelajari