Skip to main content

Що таке перевантаження функцій (overload)?

Що таке перевантаження функцій (overload)

Перевантаження функції - це можливість описати кілька сигнатур (варіантів виклику) однієї й тієї самої функції з різними типами аргументів і значень, що повертаються.

Простіше кажучи: одна функція може поводитися по-різному залежно від типів аргументів.

TypeScript дозволяє типізувати це через кілька сигнатур "зверху" і одну реалізацію "знизу".


Приклад 1. Проста перевантаженість за типом аргументу

javascript
// Перевантаження (варіанти виклику) 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. Різні типи значень, що повертаються

javascript
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. Різна кількість параметрів

javascript
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-функціях

javascript
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[] }

Як писати перевантаження правильно

Структура:

javascript
// 1. Спочатку - сигнатури перевантажень function fn(param: Type1): ReturnType1; function fn(param: Type2): ReturnType2; // 2. Потім - реалізація з union-типами function fn(param: Type1 | Type2): ReturnType1 | ReturnType2 { // логіка }

Важливо: реалізація повинна завжди обробляти всі варіанти. TypeScript перевіряє, що вона сумісна з кожною сигнатурою.


Помилки при неправильному перевантаженні

Не можна писати реалізацію перед сигнатурами перевантаження:

javascript
function fn(x: any): any { return x; } // Помилка: реалізація має бути останньою function fn(x: string): string; function fn(x: number): number;

Потрібно навпаки:

javascript
function fn(x: string): string; function fn(x: number): number; function fn(x: any): any { return x; }

Коли використовувати перевантаження

Використовуй перевантаження, якщо:

  • у функції різні типи аргументів і різні результати;
  • не можна виразити це просто через union;
  • тобі потрібно зберегти сувору типізацію значення, що повертається.

Альтернатива перевантаженню - generic

Іноді простіше виразити те саме через узагальнені типи:

javascript
function wrap<T>(value: T): { data: T } { return { data: value }; }

Generic-функції компактніші і часто кращі, якщо логіка однакова для всіх типів.


Підсумкова шпаргалка

ОсобливістьПеревантаження функцій
К-сть реалізаційЗавжди одна
К-сть сигнатурКілька зверху
Різні аргументиТак
Різні типи поверненняТак
Порядок оголошеньСигнатури -> Реалізація
Перевірка типівTS обирає підходящу сигнатуру
АльтернативаGeneric-функція

Приклад "все разом"

javascript
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

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.