Урок 2 · TypeScript Generics

Твоя перша generic-функція

Ти вже користуєшся generics — Array<T>, Promise<T>. Цей урок про один зсув: навчитися писати їх. Уся магія — в одній ідеї.

Велика ідея: <T> — це параметр. Для типів.

Звичайна функція приймає значення в дужках ( ). Generic-функція додатково приймає тип у кутових дужках < >. Хто його передає? Майже завжди — не ти вручну, а викликач, автоматично, з аргументів.

аргумент: [1, 2] T виводиться = number результат: number

T — це просто ім'я-заповнювач для типу, який стане відомий лише в момент виклику. Він зв'язує вхід із виходом.

Чому не просто any?

Спокуса: «нехай приймає будь-що — поставлю any». Але any стирає типову інформацію — і TS перестає тобі допомагати:

// any: TS більше не знає, що повернулось
function firstAny(arr: any[]): any { return arr[0]; }
const a = firstAny([1, 2]);
a.toUpperCase();   // ⚠️ компілюється, але впаде в рантаймі (number.toUpperCase)

// generic: тип зберігається, помилку видно одразу
function first<T>(arr: T[]): T { return arr[0]; }
const b = first([1, 2]);   // b: number
b.toUpperCase();   // ❌ TS-помилка ще до запуску — саме те, що треба
Тест на «потрібен generic чи any»: чи має тип виходу залежати від типу входу? Якщо так — generic. any розриває цей зв'язок назавжди.

Анатомія

function first<T>(arr: T[]): T {
  return arr[0];
}
//          ▲оголошуємо  ▲вживаємо  ▲вживаємо
//  треба ОГОЛОСИТИ один раз перед (...), далі вживай як звичайний тип.
Літера значення не має: T, Item, Element — однаково. T — лише конвенція (Type). Головне — оголосити в < > перед використанням.

Тренажер inference: який тип виведе TS?

Дано function first<T>(arr: T[]): T. Для кожного виклику обери, який тип буде у результату. Фідбек — одразу.

Перевір розуміння

1. Що головне дає <T>, чого не дає any?
2. Хто зазвичай «передає» значення для T у виклику first([1, 2])?
3. Яка сигнатура коректно описує функцію, що повертає той самий тип, який отримала?

Спробуй сам (30 секунд)

Відкрий TS Playground, встав це і наведи мишею на r1, r2, r3 — побачиш виведені типи:

function last<T>(arr: T[]): T {
  return arr[arr.length - 1];
}
const r1 = last([10, 20, 30]);     // наведи: number
const r2 = last(["a", "b"]);          // наведи: string
const r3 = last([true, false]);       // наведи: boolean

Одна функція — три різні типи, нуль any, нуль дублювання. Оце і є сила generics.

Я — твій викладач. Питай.

Готовий копати далі? Спитай мене прямо в чаті. Наприклад: