Menengah Exercism • typescript

Keajaiban Generics

Ringkasan Pelajaran

Pelajari cara menulis komponen yang dapat digunakan kembali dan aman secara tipe menggunakan TypeScript Generics.

Keajaiban Generics

Generics adalah salah satu fitur paling kuat dalam TypeScript. Mereka memungkinkan Anda membuat komponen (fungsi, kelas, atau interface) yang bekerja dengan berbagai tipe sambil tetap mempertahankan keamanan tipe (type safety) secara penuh.

Masalahnya

Bayangkan Anda ingin membuat fungsi yang mengembalikan elemen pertama dari sebuah array.

function ambilElemenPertama(arr: any[]): any {
  return arr[0];
}

const angka = [1, 2, 3];
const angkaPertama = ambilElemenPertama(angka); // TypeScript menganggap angkaPertama sebagai 'any'

Dengan menggunakan any, kita kehilangan semua informasi tipe. Kita menginginkan cara untuk mengatakan: “Fungsi ini menerima array dari suatu tipe, dan mengembalikan elemen dari tipe yang sama.”

Solusinya: Generics

Kita dapat menggunakan variabel tipe (biasanya dilambangkan dengan <T>) untuk menangkap tipe yang disediakan oleh pengguna.

function ambilElemenPertama<T>(arr: T[]): T {
  return arr[0];
}

const angka = [1, 2, 3];
const angkaPertama = ambilElemenPertama(angka); // TypeScript dengan benar menyimpulkan angkaPertama adalah 'number'

const nama = ["Alice", "Bob"];
const namaPertama = ambilElemenPertama(nama); // TypeScript dengan benar menyimpulkan namaPertama adalah 'string'

Generic Interface

Anda juga dapat menggunakan generics dengan interface untuk membuat struktur data yang fleksibel.

interface ApiResponse<T> {
  data: T;
  status: number;
  message: string;
}

interface User {
  id: number;
  name: string;
}

const userResponse: ApiResponse<User> = {
  data: { id: 1, name: "Alice" },
  status: 200,
  message: "Berhasil"
};

Generic Constraint

Terkadang Anda ingin membatasi tipe apa saja yang dapat dikirim ke sebuah generic. Anda dapat menggunakan kata kunci extends untuk menambahkan batasan (constraint).

interface MemilikiPanjang {
  length: number;
}

function catatPanjang<T extends MemilikiPanjang>(item: T): void {
  console.log(item.length);
}

catatPanjang("Halo"); // OK: String memiliki length
catatPanjang([1, 2, 3]); // OK: Array memiliki length
catatPanjang(123); // Error: Number tidak memiliki properti 'length'.

Ringkasan

Generics memungkinkan Anda untuk:

  1. Menghindari duplikasi kode: Satu fungsi dapat bekerja untuk banyak tipe.
  2. Mempertahankan Keamanan Tipe: Berbeda dengan any, generics menjaga tipe asli data Anda.
  3. Membangun API yang Fleksibel: Sangat cocok untuk fungsi utilitas, respons API, dan komponen yang dapat digunakan kembali.