Recraftory

TypeScript - Generic

Generic membuat kode yang dapat bekerja dengan berbagai tipe tanpa kehilangan informasi tipe.

Fungsi Generic

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

// Pemanggilan dengan tipe eksplisit
let hasilString = identity<string>("hello");
let hasilNumber = identity<number>(42);

// Type inference — TypeScript menebak tipe dari argumen
let hasil = identity("hello"); // T = string

Generic dengan Constraint

// T harus memiliki properti length
function panjang<T extends { length: number }>(arg: T): number {
  return arg.length;
}

panjang("hello");        // ✅ string punya length
panjang([1, 2, 3]);      // ✅ array punya length
// panjang(123);          // ❌ number tidak punya length

Generic di Interface

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

let responsePengguna: ResponseAPI<Pengguna> = {
  data: { id: 1, nama: "Alice" },
  status: 200,
  message: "OK",
};

let responseList: ResponseAPI<Pengguna[]> = {
  data: [{ id: 1, nama: "Alice" }],
  status: 200,
  message: "OK",
};

Generic di Class

class Container<T> {
  private value: T;

  constructor(value: T) {
    this.value = value;
  }

  getValue(): T {
    return this.value;
  }

  setValue(value: T): void {
    this.value = value;
  }
}

let containerString = new Container("hello");
let containerNumber = new Container(42);

Default Generic Parameter

interface Pagination<T = any> {
  data: T[];
  page: number;
  totalPages: number;
}

let defaultPagination: Pagination = {
  data: [],
  page: 1,
  totalPages: 1,
};

Keyof dan Lookup Types

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

let user = { id: 1, nama: "Alice", email: "alice@email.com" };

let id = getProperty(user, "id");       // number
let nama = getProperty(user, "nama");   // string
// getProperty(user, "tidakAda");      // ❌ Error: key tidak ada