Інші типи даних (any, unknown, tuple, enum, union type, literal type)
Any
any - це спеціальний тип. Його можна використовувати, щоб вказати, що змінна може мати будь-який тип. Це менш безпечний тип, і його слід використовувати з обережністю.
let dynamicValue: any = "Hello";
dynamicValue = 42;
Головний недолік any в тому, що його можна присвоїти змінній з іншим визначеним типом і це не буде вважатися помилкою, бо any також включає цей тип даних.
let dynamicValue: any = "Hello";
let someNumber: number = dynamicValue;
Як бачимо на прикладі в змінній dynamicValue із типом any зберігається рядок і цей рядок ми присвоюємо змінній someNumber, яка має тип число. Але TypeScript нам не покаже помилки.

Так само при використанні типу any не відбувається перевірка чи існує якийсь параметр в обʼєкті. Тобто запис наведений нижче зовсім не вкаже на помилку.
let dynamicValue: any;
// dynamicValue = { name: "Alex" };
let a = dynamicValue.name;

Unknown
Цей тип даних допомагає уникнути недоліку попереднього типу даних. Так, припустимо є змінна з типом даних unknown в якій зберігається рядок і ми її спробуємо присвоїти іншій змінній визначеній за типом даних число, то буде помилка.
let dynamicValue: unknown = "Hello";
let someNumber: number = dynamicValue;


Щоб уникнути помилки, перед присвоєнням значення потрібно перевірити тип змінної. Якщо він збігається, то присвоєння відбудеться, якщо типи даних відрізняються, то операція проігнорується.
let dynamicValue: unknown = "Hello";
let someNumber: number;
if (typeof dynamicValue === 'number') {
someNumber = dynamicValue;
}

Такі вирази називають Type Guard, тобто такі що перевіряють тип змінної.
Tuple
У TypeScript "кортеж" (Tuple) - це тип даних, який дозволяє визначити масив з фіксованою кількістю елементів, де кожен елемент може мати свій власний тип даних. Особливість кортежів полягає в тому, що вони дозволяють визначити типи для кожного елемента в масиві в певному порядку.
let person: [string, number] = ["Alice", 25];
Якщо якомусь елементу масиву спробувати записати вміст невідповідного типу даних, то буде помилка.

Кортежі особливо корисні в ситуаціях, коли потрібно мати точний контроль над типами даних і кількістю елементів у структурі даних.
Недолік: Компілятор не відстежує реальний вміст масиву тому методи масивів, наприклад метод push() він пропустить і не покаже помилки.

Enum
enum - це перелічуваний тип даних, який дозволяє створювати набір іменованих констант, які представляють цілі числові значення.
Перелічувані типи допомагають зробити код більш зрозумілим та читабельним, оскільки вони надають змінним зрозумілі та описові імена замість чисел.
Змінні в enum заведено називати з великої літери.
enum Status { Pending, InProgress, Completed}
Якщо ми виведемо в консолі значення кожного елемента в enum Status, то побачимо його числовий відповідник. По замовчуванню, enum присвоює числові значення кожній з констант, починаючи з нуля
console.log("Pending: ", Status.Pending); // 0
console.log("InProgress: ", Status.InProgress); // 1
console.log("Completed: ", Status.Completed); // 2

Однак можна призначити власні значення, якщо це потрібно:
enum Status {
Pending = 1,
InProgress = 2,
Completed = 3,
}
По суті це навіть не зовсім тип даних, а більше йде як паттерн.
Зручно використовувати для гарного коду, оскільки візуально видно, що певний статус змінної, чи, наприклад користувача ми перевіряємо не просто з якимось числом, а з візуально зрозумілим статусом (значенням).
Наприклад у нас є процес із трьома можливими статусами Pending, InProgress, Completed. І в якійсь змінній зберігається актуальний статус процесу (наприклад завантаження сторінки). В такому разі, наприклад при збігу цього статусу з одним із значень enum ми можемо ввімкнути лоадер або вимкнути. тощо. Зобразімо це в коді нижче.
enum Status {
Pending,
InProgress,
Completed,
}
const operation = {
status: Status.Pending,
};
if (operation.status === Status.Pending) {
console.log("Current operation status: ", Status.Pending);
// Current operation status: 0
}
Так само в enum ми можемо, наприклад зберігати статус користувача (ADMIN, GUEST, MODERATOR), або якийсь інший параметр.
А ось так цей код буде скомпільований в js.
var Status;
(function (Status) {
Status[Status["Pending"] = 0] = "Pending";
Status[Status["InProgress"] = 1] = "InProgress";
Status[Status["Completed"] = 2] = "Completed";
})(Status || (Status = {}));
var operation = {
status: Status.Pending,
};
if (operation.status === Status.Pending) {
console.log("Current operation status: ", Status.Pending);
}

Union Type
Об'єднання типів (Union Types) використовують для опису змінних, які можуть мати різні типи. Об'єднання типів позначається символом | між типами.
let value: number | string;
value = 42; // допустимо, оскільки number
value = "hello"; // допустимо, оскільки string
Якщо присвоїти значення іншого типу, то виникне помилка.


Коли використовується Union Type як параметр функції, це означає, що функція може приймати аргументи з будь-якого з типів визначених в об'єднанні.
function printId(id: number | string) {
console.log(id);
}
printId(123); // допустимо
printId("abc"); // допустимо
Це дуже корисний механізм, який допомагає змоделювати різні структури даних і обробляти різні типи значень в TypeScript.
Розглянемо приклад функції, яка прийматиме два параметри можливих типів число або рядок. Якщо обидва параметри числа - то функція їх додаватиме, у всіх інших випадках - виконуватиме конкатенацію.
function myFunc(value1: number | string, value2: number | string) {
if (typeof value1 === "number" && typeof value2 === "number") {
return value1 + value2;
} else {
return value1.toString() + value2.toString();
}
}
console.log("numbers: ", myFunc(1, 2));
console.log("strings: ", myFunc(1, "2"));

Literal Type
В TypeScript Literal Type - це тип, який використовує конкретне літеральне значення як тип даних. Це означає, що змінна або параметр може приймати лише конкретне значення, яке вказане як літерал. Використання літеральних типів дозволяє зробити типи більш точними та визначити можливі значення для змінних або параметрів функцій.
Рядкові літерали:
let status: "success" | "error";
status = "success"; // допустимо
status = "error"; // допустимо
status = "pending"; // помилка, так як "pending" не є відомим літералом типу
Числові літерали:
let num: 1 | 2 | 3;
num = 1; // допустимо
num = 2; // допустимо
num = 3; // допустимо
num = 4; // помилка, так як 4 не є відомим літералом типу
Літеральні типи корисні при визначенні точних значень, які змінна чи параметр може приймати, і допомагають визначити допустимі варіанти значень в коді, забезпечуючи більшу надійність і контроль.
Last updated