Пошук уроків, статей та іншого контенту
Вивчіть призначення void для функцій без результату та never для значень, які ніколи не виникають.
void: функція без корисного результатуТип void використовують переважно для позначення функцій, результат яких не потрібно використовувати.
function logMessage(message: string): void {
console.log(message);
}
logMessage("Збережено");Функція logMessage виконує побічну дію — виводить повідомлення, але не повертає значення, яке має сенс обробляти.
Якщо функція має тип void, оператор return без значення дозволений:
function printUserName(name: string): void {
if (name.length === 0) {
return;
}
console.log(name);
}Але повернення конкретного значення з функції, явно оголошеної як void, спричинить помилку:
function getMessage(): void {
// Помилка: тип string не можна повернути з функції типу void
// return "Готово";
}void не те саме, що undefinedvoid описує призначення результату — результат не використовується. undefined — це конкретне значення JavaScript.
function doNothing(): void {
// Функція не повертає значення явно
}
const result = doNothing();
// Тип result — voidФункція без оператора return фактично повертає undefined під час виконання, але її оголошений тип може бути void.
Якщо важливо явно працювати саме зі значенням undefined, потрібно вказати цей тип:
function getUndefined(): undefined {
return undefined;
}void у типах функційvoid часто використовують для опису callback-функцій:
function runCallback(callback: () => void): void {
callback();
}
runCallback(() => {
console.log("Callback виконано");
});Такий тип означає, що runCallback не очікує використовувати результат callback-функції.
У TypeScript функцію, яка повертає значення, можна передати туди, де очікується () => void:
function calculateValue(): number {
return 42;
}
runCallback(calculateValue);Результат calculateValue у цьому випадку ігнорується. Це зручно для callback-функцій, але не означає, що number і void є взаємозамінними в усіх ситуаціях.
never: значення, яке ніколи не виникаєТип never описує ситуації, у яких функція не може нормально завершитися і повернути значення.
Функція може мати тип never, якщо вона:
завжди викидає помилку;
працює нескінченно і ніколи не завершується;
переходить у стан, якого не може існувати за коректної логіки програми.
function fail(message: string): never {
throw new Error(message);
}У fail немає нормального результату. Виклик або перериває виконання винятком, або не доходить до наступного рядка.
function getUserName(userName: string | undefined): string {
if (userName === undefined) {
fail("Ім'я користувача відсутнє");
}
return userName;
}Після виклику fail TypeScript розуміє, що виконання не продовжиться звичайним шляхом. Тому userName після перевірки можна використовувати як string.
function waitForever(): never {
while (true) {
// Функція навмисно не завершується
}
}Така функція не повертає ні void, ні undefined: вона взагалі не доходить до моменту повернення.
На практиці нескінченні цикли потрібно використовувати обережно, щоб не заблокувати виконання програми.
void і never: різницяПорівняймо призначення типів:
function notify(): void {
console.log("Операцію виконано");
}
function stopProgram(): never {
throw new Error("Критична помилка");
}void: функція завершується, але не повертає корисного результату.
never: функція не завершується нормальним поверненням.
void може бути результатом виклику функції.
never означає, що результат виклику неможливо отримати.
Умовно:
void → функція завершилася без корисного значення
never → функція не завершилася нормальноnever і вичерпна перевірка switchnever корисний для перевірки, що оброблено всі варіанти обмеженого типу.
type Status = "pending" | "success" | "error";
function assertNever(value: never): never {
throw new Error(`Непередбачений статус: ${value}`);
}
function getStatusMessage(status: Status): string {
switch (status) {
case "pending":
return "Запит виконується";
case "success":
return "Запит успішний";
case "error":
return "Сталася помилка";
default:
return assertNever(status);
}
}
console.log(getStatusMessage("success"));Після обробки всіх значень типу Status TypeScript визначає, що в гілці default змінна status має тип never. Це означає: за поточним описом типу сюди неможливо потрапити.
Якщо додати новий варіант:
type Status = "pending" | "success" | "error" | "cancelled";і не додати для нього case, TypeScript повідомить про помилку в assertNever(status). Отже, зміни в типі не залишаться непоміченими.
never як тип, якого не можна матиЗмінна типу never не може містити жодного значення:
let impossibleValue: never;
// Помилки:
// impossibleValue = 0;
// impossibleValue = "text";
// impossibleValue = undefined;Це логічно: never є типом для ситуацій, які не можуть відбутися.
Тип never також з'являється, коли TypeScript бачить суперечливі умови:
function processValue(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
}
if (typeof value === "number") {
return value.toFixed(2);
}
// У цьому місці value має тип never
return assertNever(value);
}
function assertNever(value: never): never {
throw new Error(`Невідоме значення: ${value}`);
}Після перевірок string і number інших варіантів не залишається.
never для звичайної функції без результатуНеправильно:
function saveData(): never {
console.log("Дані збережено");
}Ця функція завершується нормально, тому її тип має бути void:
function saveData(): void {
console.log("Дані збережено");
}void для функції, яка завжди викидає помилкуТехнічно функція, яка має анотацію void і завжди виконує throw, може працювати, але never точніше описує її поведінку:
function fail(message: string): never {
throw new Error(message);
}Така анотація допомагає TypeScript виконувати аналіз потоку керування.
never і undefinedundefined — це значення:
const value: undefined = undefined;never — це відсутність можливого результату:
function throwError(): never {
throw new Error("Помилка");
}Функція з типом undefined завершується й повертає undefined. Функція з типом never не повертає значення взагалі.
never без реальної причиниНе потрібно використовувати never лише тому, що функція «нічого не повертає». Якщо вона завершується нормально, використовуйте void.
void описує функції, результат яких не використовується.
Функція типу void може завершитися нормально.
undefined є конкретним значенням, а void — описом призначення результату.
never описує функції, які не повертають результат, бо завжди викидають помилку або не завершуються.
never допомагає виконувати вичерпну перевірку switch та інших обмежених наборів варіантів.
Для звичайних процедур використовуйте void, а для неможливого нормального завершення — never.