Penjelasan Generik Lanjutan TypeScript dengan Contoh

Generik dalam TypeScript menyediakan cara untuk membuat komponen kode yang dapat digunakan kembali dan fleksibel dengan bekerja dengan berbagai tipe data. Generik tingkat lanjut mengembangkan konsep ini lebih jauh dengan memperkenalkan fitur tambahan seperti batasan, nilai default, dan beberapa tipe, yang memungkinkan pengembang untuk menulis kode yang lebih tangguh dan aman terhadap tipe. Dalam artikel ini, contoh akan digunakan untuk mengeksplorasi konsep tingkat lanjut ini dalam generik.

Batasan Umum

Batasan membatasi tipe yang dapat diterima oleh generik. Ini memastikan bahwa tipe yang diteruskan ke fungsi atau kelas generik memenuhi kriteria tertentu. Misalnya, batasan dapat digunakan untuk memastikan bahwa tipe generik memiliki properti atau metode tertentu.

function getLength<T extends { length: number }>(arg: T): number {
    return arg.length;
}

const stringLength = getLength("TypeScript");
const arrayLength = getLength([1, 2, 3]);

Dalam contoh ini, batasan <T extends { length: number }> memastikan bahwa argumen yang diteruskan ke getLength memiliki properti length.

Beberapa Generik

TypeScript memungkinkan penggunaan beberapa tipe generik dalam fungsi, kelas, atau antarmuka yang sama. Ini berguna saat bekerja dengan pasangan nilai atau struktur data lain yang melibatkan beberapa tipe.

function pair<T, U>(first: T, second: U): [T, U] {
    return [first, second];
}

const stringNumberPair = pair("TypeScript", 2024);

Fungsi ini, pair, menerima dua tipe generik yang berbeda, T dan U, dan mengembalikan tupel yang berisi kedua tipe tersebut.

Tipe Umum Default

Generik dalam TypeScript juga dapat memiliki tipe default. Ini berguna saat Anda ingin generik memiliki tipe fallback jika tidak ada tipe spesifik yang disediakan.

function identity<T = string>(value: T): T {
    return value;
}

const defaultString = identity("Hello");  // T is string
const customNumber = identity<number>(100);  // T is number

Dalam contoh ini, jika tidak ada tipe yang diteruskan ke identity, maka defaultnya adalah string.

Menggunakan Generik dengan Antarmuka

Generik dapat digunakan dengan antarmuka untuk menentukan struktur kompleks yang tipenya tidak tetap. Hal ini menambah fleksibilitas dalam cara mengelola data.

interface Container<T> {
    value: T;
}

const stringContainer: Container<string> = { value: "Hello" };
const numberContainer: Container<number> = { value: 42 };

Antarmuka Container dirancang untuk menampung nilai jenis apa pun, yang memungkinkan berbagai jenis kontainer dengan tipe tertentu.

Kelas Umum

Kelas-kelas dalam TypeScript juga bisa bersifat generik. Hal ini khususnya berguna saat mendesain kelas-kelas yang bekerja dengan berbagai tipe data, seperti kelas penyimpanan data atau kelas koleksi.

class DataStore<T> {
    private data: T[] = [];

    add(item: T): void {
        this.data.push(item);
    }

    getAll(): T[] {
        return this.data;
    }
}

const stringStore = new DataStore<string>();
stringStore.add("Hello");
stringStore.add("TypeScript");

const numberStore = new DataStore<number>();
numberStore.add(42);

Dalam contoh ini, kelas DataStore bekerja dengan semua jenis data, menyediakan cara yang aman untuk menyimpan dan mengambil elemen.

Kesimpulan

Generik tingkat lanjut dalam TypeScript merupakan alat yang ampuh untuk menulis kode yang fleksibel, dapat digunakan kembali, dan aman terhadap tipe. Dengan menggunakan batasan, beberapa tipe, nilai default, dan generik dalam kelas dan antarmuka, pengembang dapat menulis kode yang lebih kompleks dan tangguh. Memahami dan memanfaatkan konsep tingkat lanjut ini memungkinkan fleksibilitas yang lebih besar dan memastikan keamanan tipe di seluruh aplikasi.