Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як працюють перевантаження функцій у TypeScript і коли краще обійтися без них?

Перевантаження описують кілька способів викликати функцію з різними типами результату залежно від аргументів. Складаються з кількох сигнатур і однієї реалізації:

function parse(value: string): number;
function parse(value: number): string;
function parse(value: string | number): string | number {
  return typeof value === 'string' ? Number(value) : String(value);
}

parse('42');   // number
parse(42);     // string

Правила:

  • реалізація ззовні не видна - викликати функцію можна лише за сигнатурами перевантажень. Сигнатура реалізації має бути сумісною з усіма ними;
  • TypeScript перебирає перевантаження по черзі й бере перше відповідне - тому конкретніші ставлять вище за загальніші;
  • реалізація сама перевіряє, з яким варіантом її викликали (typeof, in), - компілятор не перевіряє, що кожна гілка повертає «правильний» тип для своєї сигнатури.

Головна пастка - аргумент-об'єднання:

declare const input: string | number;
parse(input);   // помилка: жодне перевантаження не приймає string | number

Кожне перевантаження приймає лише свій тип, а об'єднання не підходить жодному. Доводиться додавати ще одну сигнатуру (value: string | number): string | number.

Коли краще без перевантажень:

  • результат не залежить від типу аргументу - звичайний тип-об'єднання;
  • результат залежить від аргументу передбачувано - generic чи умовний тип:
function first<T>(items: T[]): T | undefined {
  return items[0];
}
  • різні способи виклику з різною кількістю параметрів - часто краще об'єкт параметрів чи кілька окремих функцій з виразними назвами (parseNumber, formatNumber).

Коли перевантаження доречні:

  • типи для API, яке вже так влаштоване - бібліотеки, .d.ts для JavaScript-коду (document.createElement('canvas') повертає HTMLCanvasElement - перевантаження в типах DOM);
  • залежність результату від літерального значення аргументу, яку незручно виразити умовним типом.

Перевантаження методів класу пишуться так само, а в типах об'єктів - кількома сигнатурами виклику.

Докладніше в документації: Перевантаження функцій

Схожі питання