You are here: Home / Topics / Generics in Typescript

Generics in Typescript

Filed under: TypeScript on 2024-03-18 12:15:16

The purpose of generics in programming languages, including TypeScript, is to provide a way to write reusable code that can work with different types while maintaining type safety. Generics allow you to define types or functions that can adapt to various data types, without sacrificing compile-time type checking.

Example 1: Generic class
index.ts:

class Box<T> {
   private value: T;
   constructor(value: T) {
       this.value = value;
   }
   getValue(): T {
       return this.value;
   }
}
// Usage
const stringBox = new Box < string > ("Hello");
console.log(stringBox.getValue()); // Output: "Hello"
const numberBox = new Box < number > (42);
console.log(numberBox.getValue()); // Output: 42

Example 2: Generic class – ArrayUtility for string and number
index.ts:

// const myFish = ["angel", "clown", "mandarin", "sturgeon"];
// const removed = myFish.splice(0, 2);
// console.log("Existing: " + myFish);
// console.log("Removed: " + removed);
class ArrayUtility<T> {
   private array: T[];
   constructor() {
       this.array = [];
   }
   add(item: T): void {
       this.array.push(item);
   }
   getItems(): T[] {
       return this.array;
   }
   remove(item: T): void {
       const index = this.array.indexOf(item);
       if (index !== -1) {
           this.array.splice(index, 1);
       }
   }
}
// Usage
const numberUtility = new ArrayUtility < number > ();
numberUtility.add(10);
numberUtility.add(20);
numberUtility.add(30);
const numbers = numberUtility.getItems();
console.log(numbers); // Output: [10, 20, 30]
const stringUtility = new ArrayUtility < string > ();
stringUtility.add("Hello");
stringUtility.add("World");
const strings = stringUtility.getItems();
console.log(strings); // Output: ["Hello", "World"]

Example 3: Generic function
index.ts:

function reverse<T>(arr: T[]): T[] {
   return arr.reverse();
}
// Usage
const numbers = [1, 2, 3, 4, 5];
const reversedNumbers = reverse(numbers);
console.log(reversedNumbers); // Output: [5, 4, 3, 2, 1]
const strings = ["apple", "banana", "cherry"];
const reversedStrings = reverse(strings);
console.log(reversedStrings); // Output: ["cherry", "banana",
"apple"]

Example 4: Generic function - Array Sorting
index.ts:

function sortArray<T>(array: T[]): T[] {
   return array.sort();
}
// Usage
const numbers: number[] = [4, 2, 1, 3];
const sortedNumbers = sortArray(numbers);
console.log(sortedNumbers); // Output: [1, 2, 3, 4]
/*********************************************** */
const strings: string[] = ["banana", "apple", "cherry"];
const sortedStrings = sortArray(strings);
console.log(sortedStrings); // Output: ["apple", "banana", "cherry"]

Example 5: Generic function - Array Mapping:
index.ts:

function mapArray<T, U>(array: T[], callback: (item: T) => U): U[] {
   return array.map(callback);
}
// Usage
const numbers: number[] = [1, 2, 3, 4, 5];
const doubledNumbers: number[] = mapArray(numbers, (num) =>
   num * 2);
console.log(doubledNumbers); // Output: [2, 4, 6, 8, 10]
const strings: string[] = ["apple", "banana", "cherry"];
const lengths: number[] = mapArray(strings, (str) => str.length);
console.log(lengths); // Output: [5, 6, 6]

Example 6: Generic Interface
index.ts:


interface Box<T> {
   value: T;
   getValue(): T;
   setValue(value: T): void;
}
// Usage
const stringBox: Box<string> = {
   value: "Laptop",
   getValue() {
       return this.value;
   },
   setValue(value) {
       this.value = value;
   },
};
console.log(stringBox.getValue()); // Output: "Laptop"
stringBox.setValue("Lenovo Laptop");
console.log(stringBox.getValue()); // Output: "Lenovo Laptop"

Example 7: Generic Interface - Repository Example
index.ts:

interface Repository<T> {
   getById(id: string): T | undefined;
   getAll(): T[];
   create(item: T): void;
   update(id: string, item: T): void;
   delete(id: string): void;
}
// Usage
interface User {
   id: string;
   name: string;
}
class UserRepository implements Repository<User> {
   private users: User[] = [];
   getById(id: string): User | undefined {
       return this.users.find((user) => user.id === id);
   }
   getAll(): User[] {
       return this.users;
   }
   create(user: User): void {
       this.users.push(user);
   }
   update(id: string, updatedUser: User): void {
       const index = this.users.findIndex((user) => user.id === id);
       if (index !== -1) {
           this.users[index] = updatedUser;
       }
   }
   delete(id: string): void {
       this.users = this.users.filter((user) => user.id !== id);
   }
}
const userRepository = new UserRepository();
// Create the User
userRepository.create({ id: "1", name: "John" });
userRepository.create({ id: "2", name: "Jane" });
// Get all users
const allUsers = userRepository.getAll();
console.log(allUsers); // Output: [{ id: "1", name: "John" }, { id: "2",
name: "Jane" }]
// Get user by id
console.log(userRepository.getById('2'));
// Update the user detail
userRepository.update('1', { id: '1', name: "George" });
// See the updated details
console.log(allUsers);

Example 8: Generic Interface
index.ts:

// Define an interface for a generic item
interface Item {
   id: number;
   name: string;
}
// Create a generic class that operates on items of type T
class ItemRepository<T extends Item> {
   private items: T[] = [];
   addItem(item: T): void {
       this.items.push(item);
   }
   getItemById(id: number): T | undefined {
       return this.items.find(item => item.id === id);
   }
   getAllItems(): T[] {
       return this.items;
   }
}
// Create instances of the generic class for different item types
// Repository for users
interface User extends Item {
   age: number;
}
const userRepository = new ItemRepository < User > ();
userRepository.addItem({ id: 1, name: "John", age: 30 });
userRepository.addItem({ id: 2, name: "Jane", age: 25 });
const user = userRepository.getItemById(1);
console.log(user); // Output: { id: 1, name: "John", age: 30 }
const allUsers = userRepository.getAllItems();
console.log(allUsers); // Output: [ { id: 1, name: "John", age: 30 }, { id: 2, name:
"Jane", age: 25 } ]
// Repository for products
interface Product extends Item {
   price: number;
}
const productRepository = new ItemRepository < Product > ();
productRepository.addItem({ id: 1, name: "Phone", price: 500 });
productRepository.addItem({ id: 2, name: "Laptop", price: 1000 });
const product = productRepository.getItemById(2);
console.log(product); // Output: { id: 2, name: "Laptop", price: 1000 }
const allProducts = productRepository.getAllItems();
console.log(allProducts); // Output: [ { id: 1, name: "Phone", price: 500 }, { id: 2,
name: "Laptop", price: 1000 } ]

About Author:
J
Java Developer     View Profile
Hi, I am using MCQ Buddy. I love to share content on this website.