📘 TypeScript

الأدوية (Generics) في TypeScript

Generic Functions

function wrap(value: T): { value: T } {
    return { value };
}

const wrappedNum = wrap(42);       // { value: 42 }
const wrappedStr = wrap("hello");  // { value: "hello" }

function zip(a: A[], b: B[]): [A, B][] {
    return a.map((item, i) => [item, b[i]]);
}
console.log(zip([1, 2], ["a", "b"]));  // [[1,"a"],[2,"b"]]

Generic Interfaces and Classes

interface Repository {
    findById(id: number): T | undefined;
    save(item: T): void;
    getAll(): T[];
}

class Stack {
    private items: T[] = [];
    push(item: T): void { this.items.push(item); }
    pop(): T | undefined { return this.items.pop(); }
    peek(): T | undefined { return this.items[this.items.length - 1]; }
    get size(): number { return this.items.length; }
}

const stack = new Stack();
stack.push(1); stack.push(2); stack.push(3);
console.log(stack.pop());   // 3
console.log(stack.size);    // 2

Generic Constraints

interface HasLength {
    length: number;
}

function logLength(item: T): void {
    console.log(`Length: ${item.length}`);
}

logLength("hello");       // Length: 5
logLength([1, 2, 3]);     // Length: 3
// logLength(42);          // ❌ Error: number has no length

Utility Types

interface User {
    id: number;
    name: string;
    email: string;
    role: string;
}

// Partial — all properties optional
type PartialUser = Partial;

// Readonly — all properties read-only
type ReadonlyUser = Readonly;

// Pick — select specific properties
type UserPreview = Pick;

// Omit — exclude specific properties
type UserWithoutRole = Omit;

// Record — build a map type
type Permissions = Record;
const perms: Permissions = { read: true, write: false };