Bagaimana Menggunakan Generics pada TypeScript
Selamat datang pada pembahasan Typescript! Hari ini, kita akan mempelajari generik
, sebuah feature di Typescript yang powerful yang memungkinkan kita untuk membuat kemponen yang dapat digunakan kembali. Generik memberikan sebuah cara untuk membuat komponen-komponen yang berkerja dengan banyak tipe data dan memberikan kemanan tipe pada saat yang bersamaan.
1. Perkenalan Generik
Generik memungkinkan kita untuk menulis fungsi, kelas dan interface yang fleksibel dan dapat digunakan berulang-ulang. Generik memungkinkan kita membuat komponen-komponen yang dapat bekerja dengan banyak tipe data tanpa kehilangan informasi tipenya.
Fungsi Generik Dasar
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("myString"); // Output: "myString"
let output2 = identity<number>(42); // Output: 42
Pada contoh ini, T
adalah tipe parameter yang bertindak sebagai sebuah placeholder untuk tipe yang asli. Ketika fungsinya dipanggil, tipe parameternya telah diganti dengan tipe yang diberikan.
2. Fungsi Generik
Kita dapat membuat fungsi generik yang bekerja dengan banyak tipe data. Ini berguna khususnya untuk fungsi yang bekerja dengan array atau koleksi.
Contoh: Fungsi Generik
function loggingIdentity<T>(arg: T[]): T[] {
console.log(arg.length); // Array has a `.length` property
return arg;
}
let stringArray = loggingIdentity<string>(["Alice", "Bob", "Charlie"]);
Disini, fungsi loggingIdentity
bekerja dengan sebuah array dari semua tipe T
. Tipe array ditentukan ketika fungsinya dipanggil.
3. Kelas Generik
Generik dapat digunakan untuk membuat kelas yang bekerja dengan berbagai tipe. Ini berguna untuk struktur data seperti stacks, queues atau linked lists.
Contoh: Kelas Generik
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
constructor(zeroValue: T, addFunction: (x: T, y: T) => T) {
this.zeroValue = zeroValue;
this.add = addFunction;
}
}
let myNumber = new GenericNumber<number>(0, (x, y) => x + y);
console.log(myNumber.add(5, 10)); // Output: 15
let myString = new GenericNumber<string>("", (x, y) => x + y);
console.log(myString.add("Hello, ", "world!")); // Output: "Hello, world!"
Pada contoh ini, kelas GenericNumber
bekerja dengan berbagai tipe T
. Tipenya dispesifikasikan ketika sebuah instance dari kelas dibuat.
4. Constraints Generik
Terkadang, kita perlu untuk membatasi tipe-tipe yang dapat digunakan dengan generik. Kita dapat mencapainya dengan constraints.
Contoh: Constraints Generik
interface Lengthwise {
length: number;
}
function loggingIdentityWithConstraint<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a `.length` property
return arg;
}
loggingIdentityWithConstraint({ length: 10, value: 42 }); // Works
// loggingIdentityWithConstraint(42); // Error: Argument of type 'number' is not assignable to parameter of type 'Lengthwise'.
Disini, tipe generic T
telah dibatasi untuk tipe-tipe yang memiliki properti length
.
5. Menggunakan Beberapa Parameter Tipe
Generik dapat juga menggunakan beberapa parameter tipe untuk membuat tipe-tipe yang lebih fleksibel dan kompleks.
Contoh: Beberapa Parameter Tipe
function merge<T, U>(obj1: T, obj2: U): T & U {
return { ...obj1, ...obj2 };
}
let mergedObject = merge({ name: "Alice" }, { age: 25 });
console.log(mergedObject); // Output: { name: "Alice", age: 25 }
Pada contoh ini, fungsi merge
menerima 2 tipe objek yang berbeda dan menggabungkannya menjadi satu.
6. Interfaces Generik
Interfaces dapat juga menggunakan generics untuk membuat kontrak untuk fungsi, kelas dan objek yang fleksibel dan dapat digunakan kembali.
Contoh: Interfaces Generik
interface KeyValuePair<K, V> {
key: K;
value: V;
}
let kvp: KeyValuePair<string, number> = { key: "age", value: 30 };
console.log(kvp); // Output: { key: "age", value: 30 }
Disini, interface keyValuePair
menerima dua parameter, K
dan V
, membuat sebuah generik interface.
7. Parameter Tipe Bawaan
Kita dapat memberikan tipe bawaan untuk generik kit, membuat opsi generik ketika memanggil fungsi atau membuat sebuah instance dari sebuah kelas.
Contoh: Parameter Tipe Bawaan
function createArray<T = string>(length: number, value: T): T[] {
return Array(length).fill(value);
}
let stringArray = createArray(3, "hello");
let numberArray = createArray<number>(3, 42);
console.log(stringArray); // Output: ["hello", "hello", "hello"]
console.log(numberArray); // Output: [42, 42, 42]
Pada contoh ini, jika tipe tidak diberikan, maka type string
bawaan akan digunakan.
8. Constraints dan keyof Generik
Menggunakan typeof
dengan generik memungkinkan kita untuk membuat fungsi yang beroperasi pada properti-properti objek yang spesifik.
Contoh: Constraints dan keyof
Generik
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
let person = { name: "Alice", age: 25 };
let name = getProperty(person, "name"); // Output: "Alice"
let age = getProperty(person, "age"); // Output: 25
// let unknown = getProperty(person, "unknown"); // Error: Argument of type '"unknown"' is not assignable to parameter of type 'keyof { name: string; age: number; }'.
Disini, fungsi getProperty
menerima sebuah object T
dan key K
yang harus menjadi sebuah key
dari T
. Ini memastikan keamanan tipe.
Contoh Kode
Disini sebuah contoh yang mencontohkan penggunaan dari generik pada fungsi, kelas dan interface:
// Generic function
function reverseArray<T>(items: T[]): T[] {
return items.reverse();
}
let reversedNumbers = reverseArray([1, 2, 3, 4, 5]);
console.log(reversedNumbers); // Output: [5, 4, 3, 2, 1]
// Generic class
class DataStorage<T> {
private data: T[] = [];
addItem(item: T) {
this.data.push(item);
}
removeItem(item: T) {
this.data = this.data.filter(i => i !== item);
}
getItems(): T[] {
return [...this.data];
}
}
let textStorage = new DataStorage<string>();
textStorage.addItem("Alice");
textStorage.addItem("Bob");
textStorage.removeItem("Alice");
console.log(textStorage.getItems()); // Output: ["Bob"]
// Generic interface
interface Pair<T, U> {
first: T;
second: U;
}
let pair: Pair<string, number> = { first: "Alice", second: 25 };
console.log(pair); // Output: { first: "Alice", second: 25 }
Rangkuman
Hari ini, kita telah mempelajari generics pada Typescript, membahas fungsi, kelas, constraint, multiple parameter tipe, interface, parameter tipe bawaan, dan operator keyof
generik.
Generik adalah sebuah fitur yang powerfull yang memungkinkan kita membuat komponen yang fleksibel, dapat digunakan kembali dan sebagai keamanan tipe.
Sumber
Subscribe to my newsletter
Read articles from Ajat Darojat directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Ajat Darojat
Ajat Darojat
A software engineer, coding instructor, and creator of Mongoloquent ORM. Active in communities and contribute to open-source projects.