Пошук уроків, статей та іншого контенту
Опишіть кортежі з фіксованою кількістю елементів і визначеними типами в кожній позиції.
Кортеж (tuple) — це тип масиву з:
фіксованою кількістю елементів;
визначеним типом для кожної позиції;
визначеним порядком елементів.
Наприклад, координати точки можна описати як кортеж із двох чисел:
let point: [number, number] = [10, 20];У цьому прикладі:
point[0] має тип number і містить координату x;
point[1] має тип number і містить координату y;
кортеж повинен містити рівно два елементи.
Кортеж відрізняється від звичайного масиву тим, що масив описує тип елементів загалом, а кортеж — тип кожної позиції окремо.
let numbers: number[] = [10, 20, 30];
let coordinate: [number, number] = [10, 20];У масиві numbers кожен елемент має тип number, а кількість елементів не обмежена. У кортежі coordinate дозволено лише дві позиції, і обидві повинні містити числа.
Тип кортежу записують у квадратних дужках:
let user: [number, string] = [1, "Olena"];Позиції мають такі типи:
user[0]; // number
user[1]; // stringПорядок типів важливий:
let correct: [number, string] = [1, "Olena"];
// Помилка: перший елемент повинен бути number
let incorrect: [number, string] = ["1", "Olena"];Також помилкою буде неправильна кількість елементів:
let tooFew: [number, string] = [1];
// Error: Source has 1 element(s) but target requires 2
let tooMany: [number, string] = [1, "Olena", true];
// Error: Source has 3 element(s) but target allows only 2TypeScript знає тип кожної позиції кортежу:
const response: [number, string] = [200, "OK"];
const statusCode = response[0]; // number
const statusText = response[1]; // stringЦе дає змогу безпечно використовувати значення:
const response: [number, string] = [200, "OK"];
console.log(response[0].toFixed(0));
console.log(response[1].toUpperCase());Якщо спробувати використати метод не того типу, TypeScript повідомить про помилку:
const response: [number, string] = [200, "OK"];
// Помилка: toUpperCase() не існує для типу number
response[0].toUpperCase();Кортежі зручно використовувати, коли функція повертає кілька значень у визначеному порядку.
function getUser(): [number, string] {
return [42, "Iryna"];
}
const user = getUser();
const id = user[0]; // number
const name = user[1]; // string
console.log(`Користувач ${name} має ідентифікатор ${id}`);Під час деструктуризації назви змінних можуть зробити значення зрозумілішими:
function getSize(): [number, number] {
return [1920, 1080];
}
const [width, height] = getSize();
console.log(`Розмір: ${width}x${height}`);Кортеж можна використовувати і для параметрів функції:
function formatUser([id, name]: [number, string]): string {
return `${id}: ${name}`;
}
console.log(formatUser([7, "Maksym"]));Функція formatUser очікує кортеж із числа та рядка саме в такому порядку.
Для кращої читабельності можна дати імена позиціям кортежу:
type User = [id: number, name: string];
const user: User = [1, "Olena"];Імена не змінюють тип і не впливають на виконання програми. Вони лише пояснюють призначення кожної позиції.
type HttpResponse = [
statusCode: number,
statusText: string
];
function getResponse(): HttpResponse {
return [200, "OK"];
}Такий запис зрозуміліший, ніж просто [number, string], особливо якщо кортеж містить кілька значень одного типу:
type Rectangle = [width: number, height: number];
const rectangle: Rectangle = [100, 50];Елемент кортежу можна зробити необов’язковим за допомогою ?.
type User = [id: number, name: string, email?: string];
const userWithoutEmail: User = [1, "Olena"];
const userWithEmail: User = [2, "Maksym", "maksym@example.com"];Необов’язковий елемент повинен розташовуватися після обов’язкових елементів:
type Settings = [theme: string, language?: string];Під час читання необов’язкове значення може бути undefined, тому це потрібно враховувати:
type User = [id: number, name: string, email?: string];
function printUser(user: User): void {
const [id, name, email] = user;
console.log(`ID: ${id}`);
console.log(`Ім'я: ${name}`);
if (email !== undefined) {
console.log(`Email: ${email}`);
}
}
printUser([1, "Olena"]);
printUser([2, "Maksym", "maksym@example.com"]);За допомогою оператора rest можна описати кортеж, у якому після обов’язкових елементів може бути довільна кількість значень певного типу.
type LogEntry = [date: Date, message: string, ...tags: string[]];
const entry: LogEntry = [
new Date(),
"Користувача створено",
"user",
"create"
];У цьому прикладі:
перший елемент — Date;
другий елемент — string;
усі наступні елементи — рядки.
function printLog([date, message, ...tags]: LogEntry): void {
console.log(date.toISOString());
console.log(message);
if (tags.length > 0) {
console.log(`Теги: ${tags.join(", ")}`);
}
}
printLog([
new Date("2025-01-01T12:00:00Z"),
"Операцію виконано",
"success",
"api"
]);Rest-елемент має бути останнім елементом типу кортежу:
type ValidTuple = [string, ...number[]];
// Некоректний варіант:
// type InvalidTuple = [...string[], number];Якщо кортеж не повинен змінюватися після створення, його можна зробити доступним лише для читання:
const coordinates: readonly [number, number] = [10, 20];
// Помилка: кортеж доступний лише для читання
coordinates[0] = 15;readonly захищає елементи кортежу від прямої зміни:
function printCoordinates(
coordinates: readonly [number, number]
): void {
const [x, y] = coordinates;
console.log(`x: ${x}, y: ${y}`);
}
printCoordinates([10, 20]);Параметр типу readonly [number, number] приймає кортеж, який не можна змінювати всередині функції.
Якщо створити масив без явної анотації, TypeScript зазвичай визначить його як масив, а не як кортеж:
const values = [10, "hello"];
// Тип: (string | number)[]Це означає, що TypeScript бачить масив із елементами типу string | number, але не фіксує тип кожної позиції.
Щоб явно отримати кортеж, потрібно вказати його тип:
const values: [number, string] = [10, "hello"];Інший спосіб — використати as const:
const values = [10, "hello"] as const;
// Тип: readonly [10, "hello"]У цьому випадку TypeScript створює незмінний кортеж із конкретними значеннями 10 і "hello", а не просто з типами number і string.
const point = [10, 20] as const;
// Тип point: readonly [10, 20]Такий кортеж можна передати функції, яка очікує readonly-кортеж:
function printPoint(point: readonly [number, number]): void {
console.log(`(${point[0]}, ${point[1]})`);
}
const point = [10, 20] as const;
printPoint(point);У наступному прикладі функція перевіряє пароль і повертає кортеж із результатом перевірки та повідомленням:
type ValidationResult = [
isValid: boolean,
message: string
];
function validatePassword(password: string): ValidationResult {
if (password.length < 8) {
return [false, "Пароль має містити щонайменше 8 символів"];
}
if (!/[A-Z]/.test(password)) {
return [false, "Пароль має містити велику літеру"];
}
return [true, "Пароль відповідає вимогам"];
}
const [isValid, message] = validatePassword("SecurePass1");
if (isValid) {
console.log("Пароль прийнято");
} else {
console.log(`Помилка: ${message}`);
}Тип ValidationResult гарантує, що функція завжди повертає:
boolean у першій позиції;
string у другій позиції.
Використовуйте кортеж, коли:
кількість позицій має значення;
кожна позиція має власне призначення;
порядок елементів є частиною контракту;
функція повертає невелику фіксовану групу значень.
Використовуйте масив, коли:
кількість елементів довільна;
усі елементи мають однакове призначення;
порядок позицій не визначає значення елемента.
// Кортеж: позиції мають різні значення
const user: [number, string] = [1, "Olena"];
// Масив: усі елементи є іменами
const names: string[] = ["Olena", "Maksym", "Iryna"];Кортеж [number, string] не варто використовувати для даних, де порядок складно запам’ятати або легко переплутати. У таких випадках об’єкт із названими властивостями може бути зрозумілішим, але для фіксованих коротких наборів значень кортеж є зручним варіантом.
const value: [number, string] = [1, "text"];Це кортеж, а не масив із довільною кількістю елементів. Додати третій елемент не можна.
type User = [number, string];
// Помилка: string не можна присвоїти типу number
const user: User = ["1", "Olena"];Типи кортежу перевіряються за позиціями, тому число у вигляді рядка "1" не є значенням типу number.
const data: (number | string)[] = [1, "Olena"];Цей тип не гарантує, що перший елемент буде числом, а другий — рядком. Якщо такий порядок важливий, потрібно використовувати кортеж:
const data: [number, string] = [1, "Olena"];type User = [id: number, name: string, email?: string];
function getEmail(user: User): string {
// Помилка: email може бути undefined
return user[2];
}Потрібно перевірити значення перед використанням або задати запасне значення:
function getEmail(user: User): string {
return user[2] ?? "Email не вказано";
}const point: readonly [number, number] = [10, 20];
// Помилка
point[0] = 30;readonly означає, що елементи можна читати, але не можна змінювати.
Кортеж описує масив із фіксованими позиціями та типами.
Синтаксис кортежу: [Type1, Type2, Type3].
Кількість і порядок елементів мають значення.
Кортежі зручно використовувати для параметрів і результатів функцій.
Необов’язкові елементи позначаються ?.
Rest-елемент ... дає змогу додати змінну кількість значень одного типу.
readonly забороняє змінювати кортеж після створення.
Якщо порядок і призначення позицій неважливі, краще використовувати звичайний масив.