TypeScript - Kelas Generik

Hello, bakal bintang pengodingan! Hari ini, kita akan melihat dunia yang menarik dari TypeScript Kelas Generik. Jangan khawatir jika Anda baru saja memulai programming; saya akan mengorbit Anda melalui perjalanan ini langkah demi langkah, seperti yang saya lakukan bagi ribuan murid selama tahun-tahun mengajar saya. Jadi, ambil minuman favorit Anda, duduk nyaman, dan mari kita mulai petualangan ini bersama!

TypeScript - Generic Classes

Kelas Generik

Apa Itu Kelas Generik?

Imaginasi Anda di toko es krim, tapi bukan untuk memilih rasa, melainkan jenis data. Itu esensi kelas generik! Mereka memungkinkan kita untuk menciptakan komponen fleksibel, yang dapat digunakan kembali dan dapat bekerja dengan jenis data yang berbeda tanpa mengorbankan keselamatan tipe.

Marilah kita mulai dengan contoh sederhana:

class Box<T> {
private content: T;

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

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

Dalam contoh ini, Box adalah kelas generik. <T> adalah seperti placeholder untuk jenis yang kita akan tentukan kemudian. Itu seperti mengatakan ke toko es krim, "Saya akan menentukan rasa saat saya memesan!"

Marilah kitauraikan:

  • class Box<T>: Ini mendeklarasikan kelas generik bernama Box dengan parameter jenis T.
  • private content: T: Kita mengatakan bahwa content akan berjenis T, apa pun T yang menjadi.
  • constructor(value: T): Konstruktor menerima nilai jenis T.
  • getValue(): T: Metode ini mengembalikan nilai jenis T.

Sekarang, mari kita lihat bagaimana kita dapat menggunakan kelas ini:

let numberBox = new Box<number>(42);
console.log(numberBox.getValue()); // Output: 42

let stringBox = new Box<string>("Hello, TypeScript!");
console.log(stringBox.getValue()); // Output: Hello, TypeScript!

Apakah itu keren? Kita telah menggunakan kelas Box yang sama untuk menyimpan baik angka dan string. Itu seperti memiliki sebuah kotak ajaib yang dapat menahan apa pun yang Anda masukkan ke dalamnya, tapi tetap ingat jenis apa yang dimiliki!

Beberapa Parameter Jenis

kadang-kadang, satu parameter jenis saja tidak cukup. Marilah kita buat contoh yang lebih kompleks dengan beberapa parameter jenis:

class Pair<T, U> {
private first: T;
private second: U;

constructor(first: T, second: U) {
this.first = first;
this.second = second;
}

getFirst(): T {
return this.first;
}

getSecond(): U {
return this.second;
}
}

Kelas Pair ini dapat menahan dua nilai yang mungkin berjenis berbeda. Itu seperti memiliki sebuah es krim ganda dimana setiap bola dapat berbeda rasa!

Marilah kita gunakan kelas Pair ini:

let pair = new Pair<string, number>("Age", 30);
console.log(pair.getFirst());  // Output: Age
console.log(pair.getSecond()); // Output: 30

Batasan Generik

Kadang-kadang, kita ingin membatasi jenis apa yang dapat digunakan dengan kelas generik kita. Kita dapat melakukan ini dengan menggunakan batasan. Itu seperti mengatakan, "Anda dapat mempunyai es krim jenis apa pun, selama itu tidak terlalu pedas!"

interface Lengthwise {
length: number;
}

class LengthChecker<T extends Lengthwise> {
checkLength(obj: T): string {
return `Panjangnya adalah: ${obj.length}`;
}
}

Dalam contoh ini, T extends Lengthwise berarti T harus jenis yang memiliki properti length. Marilah kita gunakannya:

let stringChecker = new LengthChecker<string>();
console.log(stringChecker.checkLength("Hello")); // Output: Panjangnya adalah: 5

let arrayChecker = new LengthChecker<number[]>();
console.log(arrayChecker.checkLength([1, 2, 3])); // Output: Panjangnya adalah: 3

// Ini akan menyebabkan kesalahan:
// let numberChecker = new LengthChecker<number>();
// Type 'number' does not satisfy the constraint 'Lengthwise'.

Implementasi Interface Generik dengan Kelas Generik

Sekarang, mari kita naikkan keterampilan kita ke level berikutnya dengan mengimplementasikan interface generik dengan kelas generik. Itu seperti membuat resep (interface) untuk jenis es krim yang berbeda (kelas-kelasnya)!

Pertama, marilah kita tentukan interface generik:

interface Repository<T> {
getById(id: number): T;
save(item: T): void;
}

Interface Repository ini menentukan kontrak untuk kelas yang akan mengelola penyimpanan dan pengambilan data. Sekarang, marilah kita implementasikan interface ini dengan kelas generik:

class GenericRepository<T> implements Repository<T> {
private items: T[] = [];

getById(id: number): T {
return this.items[id];
}

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

Kelas GenericRepository kita mengimplementasikan interface Repository. Itu dapat bekerja dengan jenis T apa pun. Marilah kita gunakannya:

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

let userRepo = new GenericRepository<User>();

userRepo.save({ name: "Alice", age: 30 });
userRepo.save({ name: "Bob", age: 25 });

console.log(userRepo.getById(0)); // Output: { name: "Alice", age: 30 }
console.log(userRepo.getById(1)); // Output: { name: "Bob", age: 25 }

Dalam contoh ini, kita telah menciptakan repositori untuk objek User. Tetapi keindahan implementasi generik kita adalah kita juga dapat dengan mudah menciptakan repositori untuk jenis lainnya!

Tabel Metode

Berikut ini adalah tabel ringkasan metode yang kita pelajari:

Metode Deskripsi Contoh
constructor(value: T) Membuat instance baru kelas generik new Box<number>(42)
getValue(): T Mengembalikan nilai yang disimpan dalam kelas generik numberBox.getValue()
getFirst(): T Mengembalikan nilai pertama dalam sepasang pair.getFirst()
getSecond(): U Mengembalikan nilai kedua dalam sepasang pair.getSecond()
checkLength(obj: T): string Memeriksa panjang objek (dengan batasan) stringChecker.checkLength("Hello")
getById(id: number): T Mengambil item dari repositori berdasarkan ID userRepo.getById(0)
save(item: T): void Menyimpan item ke repositori userRepo.save({ name: "Alice", age: 30 })

Dan itu adalah dia, teman-teman! Kita telah melakukan perjalanan melalui negeri TypeScript Kelas Generik, dari kotak sederhana ke repositori yang kompleks. Ingat, latihan membuat sempurna, jadi jangan takut untuk mencoba konsep ini. Siapa tahu? Anda mungkin saja menciptakan hal yang besar dalam programming! Sampaijumpa lagi, selamat coding!

Credits: Image by storyset