8.1 Основы перегрузки функций
Перегрузка функций (Function Overloads) в TypeScript позволяет объявлять несколько сигнатур для одной и той же функции, что делает ее более гибкой и универсальной. Это особенно полезно, когда функция должна обрабатывать несколько типов аргументов или возвращать разные типы в зависимости от переданных параметров.
Перегрузка функций позволяет объявлять несколько сигнатур для одной функции, каждая из которых описывает разные параметры и возвращаемые типы. Это делается путем объявления нескольких сигнатур функции перед ее фактической реализацией.
Синтаксис:
function funcName(param1: Type1): ReturnType1;
function funcName(param2: Type2): ReturnType2;
// Реализация функции
function funcName(param: Type): ReturnType {
// Логика функции
}
Каждая перегрузка функции описывает возможные комбинации параметров и возвращаемых типов, а реализация функции обрабатывает их все.
Пример перегрузки функций
Рассмотрим пример, где функция add может складывать числа и конкатенировать строки:
"use strict";
// Реализация функции
function add(a, b) {
return a + b;
}
// Использование функции
const sum = add(5, 10); // sum имеет тип number и значение 15
const concatenated = add("Hello, ", "world!"); // concatenated имеет тип string и значение "Hello, world!"
console.log(sum); // Вывод: 15
console.log(concatenated); // Вывод: Hello, world!
// Объявление дополнительных сигнатур
function add(a: number, b: number): number;
function add(a: string, b: string): string;
// Реализация функции
function add(a: any, b: any): any {
return a + b;
}
// Использование функции
const sum = add(5, 10); // sum имеет тип number и значение 15
const concatenated = add("Hello, ", "world!"); // concatenated имеет тип string и значение "Hello, world!"
console.log(sum); // Вывод: 15
console.log(concatenated); // Вывод: Hello, world!
Здесь функция add имеет две перегрузки: одну для сложения чисел и другую для конкатенации строк. Реализация функции принимает параметры типа any и возвращает результат сложения или конкатенации.
Преимущества перегрузки функций
- Гибкость: перегрузка функций позволяет одной функции обрабатывать несколько типов аргументов, что делает код более гибким.
- Типовая безопасность: перегрузка функций обеспечивает типовую безопасность, так как каждая перегрузка четко определяет типы параметров и возвращаемые значения.
- Улучшенная читаемость: перегрузка функций делает код более понятным и легким для сопровождения, так как каждая перегрузка описывает различные варианты использования функции.
8.2 Примеры использования перегрузки функций
Пример 1: Обработка различных типов данных
Рассмотрим функцию parse, которая может принимать строку или массив строк и возвращать соответствующий результат:
"use strict";
// Реализация функции
function parse(input) {
if (typeof input === "string") {
return input.split("");
}
else if (Array.isArray(input)) {
return input.map(item => item.split(""));
}
}
// Использование функции
const singleResult = parse("hello"); // singleResult имеет тип string[] и значение ["h", "e", "l", "l", "o"]
const multipleResult = parse(["hello", "world"]); // multipleResult имеет тип string[][] и значение [["h", "e", "l", "l", "o"], ["w", "o", "r", "l", "d"]]
console.log(singleResult); // Вывод: ["h", "e", "l", "l", "o"]
console.log(multipleResult); // Вывод: [["h", "e", "l", "l", "o"], ["w", "o", "r", "l", "d"]]
// Объявление сигнатур
function parse(input: string): string[];
function parse(input: string[]): string[][];
// Реализация функции
function parse(input: any): any {
if (typeof input === "string") {
return input.split("");
} else if (Array.isArray(input)) {
return input.map(item => item.split(""));
}
}
// Использование функции
const singleResult = parse("hello"); // singleResult имеет тип string[] и значение ["h", "e", "l", "l", "o"]
const multipleResult = parse(["hello", "world"]); // multipleResult имеет тип string[][] и значение [["h", "e", "l", "l", "o"], ["w", "o", "r", "l", "d"]]
console.log(singleResult); // Вывод: ["h", "e", "l", "l", "o"]
console.log(multipleResult); // Вывод: [["h", "e", "l", "l", "o"], ["w", "o", "r", "l", "d"]]
В этом примере функция parse имеет две перегрузки: одну для обработки строки и другую для обработки массива строк.
Пример 2: Функция для извлечения значений из объектов
Рассмотрим функцию getProperty, которая может извлекать значение свойства из объекта или массива объектов:
"use strict";
// Объявление сигнатур
// Реализация функции
function getProperty(objOrObjs, key) {
if (Array.isArray(objOrObjs)) {
return objOrObjs.map(obj => obj[key]);
}
else {
return objOrObjs[key];
}
}
const person = { name: "Alice", age: 25 };
const people = [{ name: "Bob", age: 30 }, { name: "Charlie", age: 35 }];
// Использование функции
const name = getProperty(person, "name"); // name имеет тип string и значение "Alice"
const ages = getProperty(people, "age"); // ages имеет тип number[] и значение [30, 35]
console.log(name); // Вывод: Alice
console.log(ages); // Вывод: [30, 35]
// Объявление сигнатур
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K];
function getProperty<T, K extends keyof T>(objs: T[], key: K): T[K][];
// Реализация функции
function getProperty<T, K extends keyof T>(objOrObjs: T | T[], key: K): T[K] | T[K][] {
if (Array.isArray(objOrObjs)) {
return objOrObjs.map(obj => obj[key]);
} else {
return objOrObjs[key];
}
}
interface Person {
name: string;
age: number;
}
const person: Person = { name: "Alice", age: 25 };
const people: Person[] = [{ name: "Bob", age: 30 }, { name: "Charlie", age: 35 }];
// Использование функции
const name = getProperty(person, "name"); // name имеет тип string и значение "Alice"
const ages = getProperty(people, "age"); // ages имеет тип number[] и значение [30, 35]
console.log(name); // Вывод: Alice
console.log(ages); // Вывод: [30, 35]
В этом примере функция getProperty имеет две перегрузки: одну для извлечения значения свойства из объекта и другую для извлечения значений свойства из массива объектов.
Ограничения и рекомендации
Хотя перегрузка функций является мощным инструментом, у нее также свои ограничения, и она требует правильного использования:
- Четкие сигнатуры: убедитесь, что каждая перегрузка функции имеет четкую и понятную сигнатуру. Это помогает избежать путаницы и улучшает читаемость кода.
- Единая реализация: реализация функции должна быть единой и обрабатывать все возможные комбинации параметров. Используйте Type Guards или другие проверки для управления различными типами аргументов.
- Минимизация перегрузок: Избегайте излишней перегрузки функций. Если функция становится слишком сложной из-за большого количества перегрузок, рассмотрите возможность разделения ее на несколько функций.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ