Memahami Generic Types dalam TypeScript untuk Fungsi, Interface, dan Class yang Fleksibel

By | 22 October 2025

Dalam dunia pemrograman modern, fleksibilitas dan reusability kode menjadi kebutuhan utama. TypeScript sebagai bahasa yang berbasis pada JavaScript menghadirkan fitur Generic Types dalam TypeScript untuk membantu pengembang menulis kode yang lebih dinamis tanpa kehilangan keamanan tipe data. Dengan generic, kita bisa membuat fungsi, interface, dan class yang mampu bekerja dengan berbagai tipe data tanpa harus menduplikasi kode.

Generic sangat berguna saat kita ingin membuat struktur data, utility function, atau komponen reusable yang tidak terbatas pada satu tipe saja. Misalnya, sebuah fungsi bisa bekerja untuk tipe string, number, atau bahkan object dengan tetap menjaga konsistensi tipe pada seluruh proses. Konsep ini menjadi pondasi penting dalam pengembangan library besar seperti React, Angular, atau bahkan struktur data kompleks seperti stack dan queue.

Apa Itu Generic TypeScript?

Generic TypeScript adalah cara untuk membuat kode yang dapat bekerja dengan berbagai tipe data, tetapi tetap menjaga tipe tersebut agar konsisten di seluruh penggunaan. Biasanya generic ditulis menggunakan tanda kurung sudut (<T>) di mana T adalah simbol tipe parameter yang bisa diganti sesuai kebutuhan.

Contoh sederhana fungsi generik:

function identity<T>(value: T): T {
  return value;
}

console.log(identity<string>("Halo")); // Output: Halo
console.log(identity<number>(123));    // Output: 123

Fungsi identity() di atas bisa menerima parameter bertipe apa pun, tetapi TypeScript akan memastikan bahwa tipe yang dikembalikan sama dengan tipe input.

Generic pada Fungsi

Generic membuat fungsi lebih fleksibel tanpa mengorbankan keamanan tipe data. Ini sangat berguna untuk membuat fungsi utilitas seperti pembungkus data, validasi, atau pengelolaan koleksi.

Contoh penggunaan generic pada fungsi:

function merge<T, U>(objA: T, objB: U): T & U {
  return { ...objA, ...objB };
}

const result = merge({ name: "Andi" }, { age: 25 });
console.log(result); // Output: { name: "Andi", age: 25 }

Pada contoh ini, kita menggunakan dua parameter tipe T dan U, lalu menggabungkannya menjadi satu objek dengan tipe gabungan T & U. TypeScript akan tetap menjaga tipe setiap properti agar tidak hilang.

Generic pada Interface

Selain fungsi, Generic TypeScript juga bisa digunakan pada interface. Hal ini memungkinkan kita membuat struktur data yang fleksibel namun tetap aman tipe.

Contoh interface generik:

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

const userResponse: ApiResponse<{ name: string; email: string }> = {
  status: 200,
  message: "Success",
  data: { name: "Budi", email: "budi@email.com" }
};

console.log(userResponse.data.name); // Output: Budi

Dengan menggunakan interface generik ApiResponse<T>, kita dapat menyesuaikan tipe data yang dikembalikan dari API sesuai konteks, seperti user, produk, atau artikel.

Generic pada Class

Generic juga bisa diterapkan pada class untuk membuat struktur data yang dapat digunakan dengan berbagai tipe. Contoh paling umum adalah implementasi stack atau queue.

Contoh class generik Stack<T>:

class Stack<T> {
  private items: T[] = [];

  push(item: T): void {
    this.items.push(item);
  }

  pop(): T | undefined {
    return this.items.pop();
  }

  peek(): T | undefined {
    return this.items[this.items.length - 1];
  }

  get size(): number {
    return this.items.length;
  }
}

const numberStack = new Stack<number>();
numberStack.push(10);
numberStack.push(20);
console.log(numberStack.peek()); // Output: 20
console.log(numberStack.pop());  // Output: 20

const stringStack = new Stack<string>();
stringStack.push("TypeScript");
stringStack.push("Generic");
console.log(stringStack.size); // Output: 2

Dalam contoh di atas, class Stack<T> dapat menyimpan elemen bertipe apa pun — baik number, string, atau bahkan object. TypeScript memastikan bahwa semua elemen dalam satu stack memiliki tipe yang konsisten.

Generic dengan Batasan (Constraints)

Kadang kita ingin membatasi jenis data yang bisa digunakan dalam generic. TypeScript menyediakan fitur constraints menggunakan kata kunci extends.

Contoh constraints pada generic:

function getLength<T extends { length: number }>(item: T): number {
  return item.length;
}

console.log(getLength("TypeScript")); // Output: 10
console.log(getLength([1, 2, 3]));    // Output: 3

Fungsi di atas hanya menerima parameter yang memiliki properti length, seperti string atau array. Jika kita mencoba memasukkan angka (number), TypeScript akan memberikan error karena tidak memiliki properti length.

Kelebihan Menggunakan Generic TypeScript

Beberapa keuntungan utama menggunakan Generic TypeScript antara lain:

Fleksibel: Satu fungsi atau class bisa bekerja dengan berbagai tipe data.

Aman tipe: TypeScript tetap menjaga kesesuaian tipe antar bagian kode.

Dapat digunakan ulang: Mengurangi duplikasi kode untuk berbagai tipe data.

Mudah di-maintain: Perubahan pada logika tidak memengaruhi tipe data di seluruh aplikasi.

Kesimpulan

Fitur Generic TypeScript memungkinkan pengembang menulis kode yang aman, efisien, dan fleksibel untuk berbagai kebutuhan. Baik untuk fungsi, interface, maupun class, generic membantu menjaga konsistensi tipe tanpa membatasi fleksibilitas penggunaan.

Dengan memahami konsep ini dan mencoba contoh seperti Generic Stack<T>, kamu akan lebih siap membangun aplikasi besar dengan struktur kode yang bersih dan scalable.

Langkah berikutnya dalam seri ini adalah mempelajari Generic Constraint dan Utility Types agar kamu dapat memanfaatkan kekuatan penuh sistem tipe TypeScript dalam proyek nyata.