Template Literal Types

Menyusun tipe string dari potongan literal dan union (`on${Event}`), memakai Uppercase/Lowercase/Capitalize/Uncapitalize, dan pola praktis untuk rute, nama event, dan kelas CSS.

Part 18 dari 24 ± 40 menit Gratis

Template literal, sekarang di dunia tipe

Kamu sudah tahu template literal di JavaScript: `Halo ${nama}`. TypeScript membawa sintaks yang sama ke dunia tipe untuk membuat tipe string baru dari potongan-potongan.

type Salam = `Halo ${string}`

const a: Salam = "Halo Dunia"     // ✅
const b: Salam = "Hai Dunia"      // ❌ Type '"Hai Dunia"' is not assignable to type '`Halo ${string}`'

Tipe Salam artinya "string apa pun yang diawali Halo ". Berguna untuk memvalidasi bentuk teks sejak kompilasi.

Mengalikan union

Kekuatan sebenarnya muncul saat bagian dalam ${ } berupa union: TypeScript menghasilkan semua kombinasi.

type Sisi = "atas" | "bawah" | "kiri" | "kanan"
type Margin = `margin-${Sisi}`
// "margin-atas" | "margin-bawah" | "margin-kiri" | "margin-kanan"

type Ukuran = "kecil" | "besar"
type Warna = "merah" | "biru"
type KelasTombol = `btn-${Ukuran}-${Warna}`
// 2 × 2 = 4 kombinasi: "btn-kecil-merah" | "btn-kecil-biru" | "btn-besar-merah" | "btn-besar-biru"

Tidak perlu menulis 4 (atau 40) kombinasi tangan — dan tidak ada yang terlewat.

Utility untuk huruf

TipeContohHasil
Uppercase<S>Uppercase<"halo">"HALO"
Lowercase<S>Lowercase<"HALO">"halo"
Capitalize<S>Capitalize<"halo">"Halo"
Uncapitalize<S>Uncapitalize<"Halo">"halo"

Pola 1: nama event

type Aksi = "klik" | "hover" | "fokus"
type NamaHandler = `on${Capitalize<Aksi>}`      // "onKlik" | "onHover" | "onFokus"

type Handler = { [K in NamaHandler]?: () => void }
const h: Handler = { onKlik: () => console.log("diklik") }
const salah: Handler = { onKlikk: () => {} }          // ❌ typo ketahuan

Pola 2: rute dan URL

type Metode = "GET" | "POST"
type Rute = `/${string}`
function panggil(metode: Metode, rute: Rute) { /* ... */ }

panggil("GET", "/pengguna")      // ✅
panggil("GET", "pengguna")       // ❌ harus diawali "/"

type Endpoint = `${Metode} ${Rute}`    // "GET /…" | "POST /…"

Pola 3: id bertipe

type IdPengguna = `user_${number}`
type IdPesanan = `ord_${number}`

const u: IdPengguna = "user_42"     // ✅
const o: IdPesanan = "user_42"      // ❌ tidak boleh tertukar

Menarik informasi dengan infer

Dikombinasikan dengan conditional type, template literal bisa mem-parsing string di level tipe:

type AmbilNama<S> = S extends `halo-${infer N}` ? N : never
type N1 = AmbilNama<"halo-budi">     // "budi"
type N2 = AmbilNama<"hai-budi">      // never

type Ekstensi<F> = F extends `${string}.${infer E}` ? E : ""
type E1 = Ekstensi<"foto.png">       // "png"

Pustaka seperti router bertipe memakai teknik ini untuk memahami "/pengguna/:id" dan menghasilkan tipe parameter { id: string }.

Kapan memakai?

  • Nama kelas/properti/event yang mengikuti pola tetap (BEM, onX, getX).
  • Memvalidasi format string sederhana (diawali, diakhiri, mengandung).
  • Menghindari string longgar yang menampung typo.

Jangan terlalu jauh: jumlah kombinasi bisa meledak (3 × 4 × 5 × 6 = 360 anggota union) dan memperlambat editor. Untuk pola longgar gunakan ${string} alih-alih menyebutkan semua kemungkinan.

Kesalahan umum pemula

  • Memakai template literal type untuk validasi runtime. Ia hanya memeriksa saat kompilasi; input dari pengguna tetap harus divalidasi.
  • Lupa membungkus union dengan Capitalize<> saat ingin huruf kapital di awal.

Praktikkan langsung, gratis

Tulis dan jalankan kode langsung di browser, dapatkan penilaian otomatis. Daftar gratis kapan saja untuk menyimpan progres dan meraih sertifikat.

Coba latihan sekarang, tanpa daftar
Bagikan: WhatsApp Facebook LinkedIn X