Содержание
👋 Привет, друзья! В этом посте я хочу затронуть тему перегрузки функций и объяснить, почему так важно понимать эту концепцию и почему не стоит бояться ее использовать!
📃 Вики-определение
Перегрузка функций или перегрузка методов - это возможность создания нескольких одноименных функций с разными реализациями. При вызове перегруженной функции будет выполняться определенная версия этой функции, соответствующая контексту вызова.
🧐 Викификация Пояснение
В двух словах перегрузка функции - это функция с несколькими сигнатурами вызова. Это означает, что существует несколько способов вызова функции.
Пример: Давайте рассмотрим пример функции, которая может быть вызвана несколькими способами с разными аргументами
type ProductParams = {
promo?: boolean;
isArchived?: boolean;
};
function getProducts(params: ProductParams) {
const url = new URL('/api/v1/products');
const urlParams = new URLSearchParams();
if ('promo' in params) {
urlParams.append('promo', params.promo.toString());
}
if ('isArchived' in params) {
urlParams.append('isArchived', params.isArchived.toString());
}
url.search = urlParams.toString();
return fetch(url.toString()).then((res) => res.json());
}
Вы можете вызвать эту функцию двумя разными способами, с двумя разными параметрами. Наша функция будет возвращать из API продукты, которые могут быть promo или archived, или как promo, так и archived.
🔍 Множественные подписи функций
Подход Typescript к перегрузке функций довольно сильно отличается от некоторых других языков. Вместо нескольких определений функций в TypeScript используется несколько сигнатур функций, за которыми следует одно тело функции.
Программа проверки типов оценивает эти сигнатуры сверху вниз. Этот порядок имеет значение, потому что TypeScript будет использовать первую сигнатуру, которая соответствует вызову функции. Например, если вызов функции может соответствовать двум перегруженным сигнатурам, TypeScript выберет ту, которая указана первой. Поэтому рекомендуется перечислять более конкретные сигнатуры выше, а более широкие - ниже.
💻 Давайте реализуем перегрузку для примера функции
// Интерфейсы продуктов
интерфейс PromoProducts {
//... некоторые свойства, специфичные для промо-продуктов
}
интерфейс ArchivedProducts {
//... некоторые свойства, характерные для архивных продуктов
}
интерфейс PromoAndArchivedProducts {
//... некоторые свойства, объединяющие промо- и архивные продукты
}
type ProductParams = {
promo?: boolean;
isArchived?: boolean;
};
// Сигнатуры перегрузки функций
function getProducts(params: { promo: true }): Promise<PromoProducts>;
function getProducts(params: { isArchived: true }): Promise<ArchivedProducts>;
function getProducts(params: { promo: true; isArchived: true }): Promise<PromoAndArchivedProducts>;
function getProducts(params: ProductParams) {
const url = new URL('/api/v1/products');
const urlParams = new URLSearchParams();
if ('promo' in params) {
urlParams.append('promo', params.maxPrice.toString());
}
if ('isArchived' in params) {
urlParams.append('isArchived', params.isArchived.toString());
}
url.search = urlParams.toString();
return fetch(url.toString()).then((res) => res.json());
}
После реализации мы сможем использовать нашу функцию различными способами и будем иметь определенный тип безопасности.
🏁 Finish
Я рекомендую не бояться использовать перегрузку функций. Это очень полезно, когда вы предоставляете интерфейсы с большим количеством типов и стремитесь к лучшей читаемости и безопасности кода.