TypeScript - Generic Classes
Hai, para bintang pemrograman masa depan! Hari ini, kita akan melihat dunia menarik TypeScript Generic Classes. Jangan khawatir jika Anda baru saja memulai pemrograman; saya akan memandu Anda melalui perjalanan ini langkah demi langkah, seperti yang saya lakukan untuk ribuan murid selama tahun-tahun mengajar. Jadi, ambil minuman favorit Anda, duduk nyaman, dan mari kita mulai petualangan ini bersama!
Generic Classes
Apa Itu Generic Classes?
Bayangkan Anda di toko es krim, tapi bukan untuk memilih rasa, melainkan jenis data. Itu esensi generic classes! Mereka memungkinkan kita untuk menciptakan komponen fleksibel dan dapat digunakan kembali yang dapat bekerja dengan jenis data yang berbeda tanpa mengorbankan keamanan tipe.
mari 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 generic. <T>
adalah seperti placeholder untuk jenis yang akan kita tentukan kemudian. Itu seperti mengatakan ke toko es krim, "Saya akan memutuskan rasa saat saya memesan!"
mari kitauraikan ini:
-
class Box<T>
: Ini mendeklarasikan kelas generic 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 menarik? Kita telah menggunakan kelas Box
yang sama untuk menyimpan baik number dan string. Itu seperti memiliki kotak ajaib yang dapat menahan apa pun yang Anda masukkan ke dalamnya, tetapi tetap ingat jenis apa yang dimiliki!
Beberapa Parameter Jenis
kadang-kadang, satu parameter jenis saja tidak cukup. mari 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 jenis yang mungkin berbeda. Itu seperti memiliki es krim berdua di mana setiap scoop dapat memiliki rasa yang berbeda!
mari gunakan kelas Pair
kami:
let pair = new Pair<string, number>("Age", 30);
console.log(pair.getFirst()); // Output: Age
console.log(pair.getSecond()); // Output: 30
Batasan Generic
kadang-kadang, kita ingin membatasi jenis apa saja yang dapat digunakan dengan kelas generic kita. Kita dapat melakukan ini menggunakan batasan. Itu seperti mengatakan, "Anda dapat memesan es krim rasa 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
. mari gunakan ini:
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 Generic dengan Kelas Generic
Sekarang, mari kita tingkatkan keterampilan kita dengan mengimplementasikan interface generic dengan kelas generic. Itu seperti membuat resep (interface) untuk jenis es krim yang berbeda (kelas)!
Pertama, mari kita tentukan interface generic:
interface Repository<T> {
getById(id: number): T;
save(item: T): void;
}
Interface Repository
ini mendefinisikan kontrak untuk kelas yang akan mengelola penyimpanan dan pengambilan data. Sekarang, mari kita implementasikan interface ini dengan kelas generic:
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
kami mengimplementasikan interface Repository
. Itu dapat bekerja dengan jenis apa pun T
. mari gunakan ini:
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 generic kita adalah kita dapat dengan mudah menciptakan repositori untuk jenis lainnya!
Tabel Metode
Berikut adalah tabel praktis yang menggabungkan metode yang kita pelajari:
Metode | Deskripsi | Contoh |
---|---|---|
constructor(value: T) |
Membuat instance baru dari kelas generic | new Box<number>(42) |
getValue(): T |
Mengembalikan nilai yang disimpan dalam kelas generic | numberBox.getValue() |
getFirst(): T |
Mengembalikan nilai pertama dalam pasangan | pair.getFirst() |
getSecond(): U |
Mengembalikan nilai kedua dalam pasangan | 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 saja, teman-teman! Kita telah melakukan perjalanan melalui negeri TypeScript Generic Classes, dari kotak sederhana ke repositori kompleks. Ingat, latihan membuat sempurna, jadi jangan khawatir untuk mencoba konsep ini. Siapa tahu? Anda mungkin menciptakan hal yang besar dalam pemrograman! Sampaijumpa lagi, selamat coding!
Credits: Image by storyset