Що таке перевантаження функцій (overload)?
Що таке перевантаження функцій (overload)
Перевантаження функції - це можливість описати кілька сигнатур (варіантів виклику) однієї й тієї самої функції з різними типами аргументів і значень, що повертаються.
Простіше кажучи: одна функція може поводитися по-різному залежно від типів аргументів.
TypeScript дозволяє типізувати це через кілька сигнатур "зверху" і одну реалізацію "знизу".
Приклад 1. Проста перевантаженість за типом аргументу
// Перевантаження (варіанти виклику)
function reverse(value: string): string;
function reverse(value: number[]): number[];
// Реалізація (одна на всі випадки)
function reverse(value: string | number[]): string | number[] {
if (typeof value === "string") {
return value.split("").reverse().join("");
} else {
return value.slice().reverse();
}
}
// Приклади використання
const str = reverse("TypeScript"); // string
const arr = reverse([1, 2, 3]); // number[]TypeScript розуміє, що:
- якщо ти передав
string-> функція повертаєstring - якщо
number[]-> повертаєnumber[]
Як це працює
TypeScript бачить усі сигнатури, але перевіряє їх згори вниз. Коли знаходить підходящу - застосовує її. Реалізація при цьому не видна користувачу - вона слугує лише для виконання.
Приклад 2. Різні типи значень, що повертаються
function toArray(value: string): string[];
function toArray(value: number): number[];
function toArray(value: string | number): (string | number)[] {
return [value];
}
toArray("hi"); // string[]
toArray(42); // number[]Приклад 3. Різна кількість параметрів
function createUser(name: string): { name: string };
function createUser(name: string, age: number): { name: string; age: number };
function createUser(name: string, age?: number) {
return age ? { name, age } : { name };
}
createUser("Tim"); // { name: string }
createUser("Tim", 25); // { name: string; age: number }Тут дві сигнатури описують, які комбінації аргументів допустимі, а реалізація об'єднує їх в одному тілі.
Приклад 4. Перевантаження в generic-функціях
function wrap<T>(value: T): { data: T };
function wrap<T>(value: T[]): { data: T[] };
function wrap<T>(value: T | T[]): { data: T | T[] } {
return { data: value };
}
wrap(42); // { data: number }
wrap([1, 2]); // { data: number[] }Як писати перевантаження правильно
Структура:
// 1. Спочатку - сигнатури перевантажень
function fn(param: Type1): ReturnType1;
function fn(param: Type2): ReturnType2;
// 2. Потім - реалізація з union-типами
function fn(param: Type1 | Type2): ReturnType1 | ReturnType2 {
// логіка
}Важливо: реалізація повинна завжди обробляти всі варіанти. TypeScript перевіряє, що вона сумісна з кожною сигнатурою.
Помилки при неправильному перевантаженні
Не можна писати реалізацію перед сигнатурами перевантаження:
function fn(x: any): any { return x; } // Помилка: реалізація має бути останньою
function fn(x: string): string;
function fn(x: number): number;Потрібно навпаки:
function fn(x: string): string;
function fn(x: number): number;
function fn(x: any): any { return x; }Коли використовувати перевантаження
Використовуй перевантаження, якщо:
- у функції різні типи аргументів і різні результати;
- не можна виразити це просто через
union; - тобі потрібно зберегти сувору типізацію значення, що повертається.
Альтернатива перевантаженню - generic
Іноді простіше виразити те саме через узагальнені типи:
function wrap<T>(value: T): { data: T } {
return { data: value };
}Generic-функції компактніші і часто кращі, якщо логіка однакова для всіх типів.
Підсумкова шпаргалка
| Особливість | Перевантаження функцій |
|---|---|
| К-сть реалізацій | Завжди одна |
| К-сть сигнатур | Кілька зверху |
| Різні аргументи | Так |
| Різні типи повернення | Так |
| Порядок оголошень | Сигнатури -> Реалізація |
| Перевірка типів | TS обирає підходящу сигнатуру |
| Альтернатива | Generic-функція |
Приклад "все разом"
function format(input: string): string;
function format(input: number): string;
function format(input: boolean): string;
function format(input: string | number | boolean): string {
return `Значення: ${input.toString()}`;
}
format("hi"); // string
format(123); // string
format(true); // stringКоротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.