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!
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 bernamaBox
dengan parameter jenisT
. -
private content: T
: Kita mengatakan bahwacontent
akan berjenisT
, apa punT
yang menjadi. -
constructor(value: T)
: Konstruktor menerima nilai jenisT
. -
getValue(): T
: Metode ini mengembalikan nilai jenisT
.
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