Generics
Generic Function (Single Parameter)
function identity<T>(arg: T): T {
return arg;
}
const num = identity(42);
const str = identity("hello");
Generic Function (Arrays)
function getFirst<T>(arr: T[]): T | undefined {
return arr[0];
}
const n = getFirst([1, 2, 3]);
const s = getFirst(["a", "b"]);
Generic Function (Multiple Parameters)
function pair<T, U>(first: T, second: U): [T, U] {
return [first, second];
}
const p = pair(1, "one");
Generic Constraints (extends)
function logLength<T extends { length: number }>(item: T): void {
console.log(item.length);
}
logLength("hello");
logLength([1, 2]);
// logLength(123); // Error
Generic Constraints (keyof)
function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: "Alice", age: 30 };
const age = getProp(user, "age");
Generic Interfaces
interface Box<T> {
value: T;
}
const box: Box<number> = { value: 10 };
Generic Classes
class Queue<T> {
private data: T[] = [];
push(item: T) { this.data.push(item); }
pop(): T | undefined { return this.data.shift(); }
}
const q = new Queue<string>();
q.push("task");
Generic Type Aliases
type Result<T> = { success: true; data: T } | { success: false; error: string };
const r: Result<number> = { success: true, data: 42 };
Conditional Types
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
Mapped Types
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
interface User { id: number; name: string; }
type ReadonlyUser = Readonly<User>;
Generic API Response Wrapper
interface ApiResponse<T> {
data: T;
status: number;
error?: string;
}
async function fetchUser(): Promise<ApiResponse<{ name: string }>> {
return { data: { name: "Alice" }, status: 200 };
}
Generic Repository Class
class Repository<T extends { id: number }> {
private items: T[] = [];
add(item: T) { this.items.push(item); }
findById(id: number): T | undefined {
return this.items.find(x => x.id === id);
}
}
Generic Event Emitter
class EventEmitter<T extends Record<string, any>> {
emit<K extends keyof T>(event: K, data: T[K]) { /* ... */ }
on<K extends keyof T>(event: K, cb: (data: T[K]) => void) { /* ... */ }
}
type Events = { login: { user: string }; logout: void };
const bus = new EventEmitter<Events>();
bus.emit("login", { user: "Alice" });