Пошук уроків, статей та іншого контенту
Створюємо узагальнені функції з параметрами типу та викликаємо їх із різними типами даних.
Узагальнена функція — це функція, яка може працювати з різними типами даних, зберігаючи інформацію про тип.
Замість того щоб створювати окрему функцію для чисел, рядків і об’єктів, ми створюємо одну функцію з параметром типу.
Параметр типу записують у кутових дужках після імені функції:
function identity<T>(value: T): T {
return value;
}T — це параметр типу. Він не є конкретним типом, а своєрідним заповнювачем, який TypeScript замінить на потрібний тип під час виклику функції.
Функція identity повертає отримане значення без змін:
function identity<T>(value: T): T {
return value;
}
const numberResult = identity(42);
const stringResult = identity("TypeScript");
const booleanResult = identity(true);
console.log(numberResult); // 42
console.log(stringResult); // TypeScript
console.log(booleanResult); // trueTypeScript сам визначає значення параметра T:
для identity(42) тип T — number;
для identity("TypeScript") тип T — string;
для identity(true) тип T — boolean.
Тому результати мають правильні типи:
const numberResult = identity(42); // number
const stringResult = identity("TypeScript"); // string
const booleanResult = identity(true); // booleanБез узагальнення можна було б написати функцію з типом any:
function identityWithAny(value: any): any {
return value;
}Але any вимикає перевірку типів. TypeScript не зможе гарантувати, який тип буде повернуто.
Узагальнена функція зберігає конкретний тип:
function identity<T>(value: T): T {
return value;
}
const result = identity("hello");
// TypeScript знає, що result має тип string
console.log(result.toUpperCase());У цьому випадку тип string не втрачається.
Зазвичай TypeScript сам визначає параметр типу. Але його можна передати явно під час виклику:
function identity<T>(value: T): T {
return value;
}
const message = identity<string>("Привіт");
const count = identity<number>(10);
console.log(message);
console.log(count);Синтаксис виклику:
ім’яФункції<Тип>(значення);Явне передавання типу корисне, коли тип не можна надійно визначити з аргументів або коли ми хочемо зробити його очевидним для читача.
Значення аргументу має відповідати вказаному типу:
function identity<T>(value: T): T {
return value;
}
const text = identity<string>("TypeScript");
// Помилка: number не можна передати як string
// const invalid = identity<string>(123);Параметр типу можна використовувати всередині типу масиву.
Наприклад, функція може повернути перший елемент масиву:
function first<T>(items: T[]): T | undefined {
return items[0];
}
const firstNumber = first([10, 20, 30]);
const firstWord = first(["one", "two", "three"]);
console.log(firstNumber); // 10
console.log(firstWord); // oneTypeScript визначає:
T як number для масиву чисел;
T як string для масиву рядків.
Оскільки масив може бути порожнім, функція може повернути undefined. Тому тип результату — T | undefined.
Це означає: результатом буде або значення типу T, або undefined.
Функція може мати кілька параметрів типу. Наприклад, функція для створення пари значень:
function makePair<T, U>(first: T, second: U): [T, U] {
return [first, second];
}
const numberAndString = makePair(1, "one");
const booleanAndArray = makePair(true, [1, 2, 3]);
console.log(numberAndString); // [1, "one"]
console.log(booleanAndArray); // [true, [1, 2, 3]]У першому виклику:
T — number;
U — string.
У другому виклику:
T — boolean;
U — number[].
Порядок типів відповідає порядку параметрів функції.
Нижче наведено приклад, який можна зберегти у файл generic-functions.ts і виконати після компіляції TypeScript:
function identity<T>(value: T): T {
return value;
}
function first<T>(items: T[]): T | undefined {
return items[0];
}
function makePair<T, U>(firstValue: T, secondValue: U): [T, U] {
return [firstValue, secondValue];
}
const numberValue = identity(42);
const stringValue = identity("TypeScript");
const firstNumber = first([10, 20, 30]);
const firstWord = first(["generic", "function"]);
const userPair = makePair("Олена", 28);
console.log(numberValue);
console.log(stringValue);
console.log(firstNumber);
console.log(firstWord);
console.log(userPair);Після компіляції TypeScript перевірить типи всіх викликів:
numberValue матиме тип number;
stringValue матиме тип string;
firstNumber матиме тип number | undefined;
firstWord матиме тип string | undefined;
userPair матиме тип [string, number].
Розглянемо оголошення:
function makePair<T, U>(firstValue: T, secondValue: U): [T, U] {
return [firstValue, secondValue];
}Його можна прочитати так:
Функція має два параметри типу: T і U.
Перший аргумент має тип T.
Другий аргумент має тип U.
Функція повертає кортеж [T, U].
Типи T і U визначаються під час виклику.
Параметри типу пов’язують типи аргументів із типом результату. Саме тому TypeScript може зберегти точну інформацію про дані.
any замість параметра типуfunction getValue(value: any): any {
return value;
}Така функція працює з будь-якими даними, але результат втрачає конкретний тип.
Краще використати узагальнену функцію:
function getValue<T>(value: T): T {
return value;
}Параметр типу існує лише під час перевірки типів. Його не можна використовувати як звичайне значення в JavaScript-коді:
function invalid<T>(value: T): T {
// T не є значенням, яке можна вивести в консоль
// console.log(T);
return value;
}T можна використовувати в анотаціях типів:
function valid<T>(value: T): T {
const result: T = value;
return result;
}Якщо тип передано явно, аргумент повинен йому відповідати:
function identity<T>(value: T): T {
return value;
}
const validValue = identity<number>(100);
// Помилка типів:
// const invalidValue = identity<number>("100");Рядок "100" є типом string, а не number.
undefined для порожнього масивуФункція, яка повертає елемент масиву, може не знайти його:
function first<T>(items: T[]): T | undefined {
return items[0];
}Не слід оголошувати результат лише як T, оскільки для порожнього масиву результатом буде undefined.
Узагальнені функції працюють із різними типами без дублювання коду.
Параметри типу записують у кутових дужках, наприклад <T>.
TypeScript часто сам визначає значення параметра типу з аргументів.
Тип можна передати явно: identity<string>("text").
Узагальнення допомагають зберігати точний тип результату.
Функція може мати кілька параметрів типу, наприклад <T, U>.
Параметр типу використовується в описах типів, але не є звичайним значенням під час виконання програми.