جنریکها تا روزی که از نوشتن سه تابع تکراری نجاتت ندهند، به نظر آکادمیک میآیند. بگذارید از پایه شهریت بسازیم.
لحظهی هویتی
typescript
function identity<T>(value: T): T {
return value;
}
identity<string>("hello"); // string
identity(42); // number — استنتاج خودکار
T یک نوع جایگزین است: فراخوانها تصمیم میگیرند چه باشد.
تابعی که واقعاً استفاده میکنی
typescript
function firstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
const name = firstElement(["آنا", "بن"]); // string | undefined
محدودیتها
typescript
function getLength<T extends { length: number }>(item: T): number {
return item.length;
}
getLength("text"); // 4
getLength([1, 2]); // 2
تایپ شرطی — حرکت قدرتمند
typescript
type Unwrap<T> = T extends Promise<infer U> ? U : T;
type A = Unwrap<Promise<number>>; // number
type B = Unwrap<string>; // string
کامپوننت جنریک
tsx
function Stack<T extends { id: string }>({ items }: { items: T[] }) {
return <div>{items.map((i) => <span key={i.id}>{i.id}</span>)}</div>;
}
قوانین طلایی
- به استنتاج اعتماد کن؛ فقط وقتی حاشیهنویسی کن که استنتاج شکست بخورد.
- با
extendsمحدود کن، نهany. - برای حالتهای ساده
T، وگرنه اسم واقعی بده (TItem).
جنریکها فقط نوعهایی با پارامتر هستند. وقتی این را با صدای بلند بگویی، سردرد حل میشود.