Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
В чем разница между Void и Never?
Void и Never — это специальные типы в TypeScript, которые указывают на отсутствие возвращаемого значения, но означают разные вещи. Различие между ними критично для правильной типизации функций.
Void — "нет возвращаемого значения"
Void означает, что функция ничего не возвращает (или возвращает undefined). Это самый распространённый тип для функций, которые выполняют действия, но не возвращают результат.
// Функция ничего не возвращает
function printMessage(message: string): void {
console.log(message);
// return; — неявно возвращает undefined
}
// Это валидно
function greet(name: string): void {
console.log(`Hello, ${name}`);
}
// Это тоже валидно (явный возврат undefined)
function sayGoodbye(): void {
console.log('Bye!');
return undefined; // ✅ Допустимо
}
Never — "функция никогда не вернёт управление"
Never указывает, что функция никогда не завершит работу нормально. Функция либо выбросит исключение, либо будет работать бесконечно, либо завершит программу.
// Функция выбрасывает исключение
function throwError(message: string): never {
throw new Error(message);
}
// Функция бесконечный цикл
function infiniteLoop(): never {
while (true) {
// do something forever
}
}
// Функция завершает процесс
function exitProcess(): never {
process.exit(1);
}
Основные различия
| Аспект | Void | Never |
|---|---|---|
| Возвращаемое значение | undefined | Нет возврата |
| Завершение | Функция завершается нормально | Функция никогда не завершается |
| Примеры | Логирование, обновление DOM | Throw, бесконечный цикл |
| Использование | Частое в обычном коде | Редкое, для специальных случаев |
Практические примеры
Void в обработчиках событий:
// Обработчик события ничего не возвращает
const handleClick = (): void => {
console.log('Button clicked');
updateUI();
};
// React компонент с обработчиком
function Button() {
return (
<button onClick={(): void => console.log('Clicked!')}>
Click me
</button>
);
}
Never в функциях-ошибок:
// Функция для выброса ошибок
function assertNotNull<T>(value: T | null): asserts value is T {
if (value === null) {
throw new Error('Value is null');
}
}
// Функция, которая должна прекратить выполнение
function handleError(error: Error): never {
console.error('Critical error:', error);
throw error;
}
// Функция для логирования и завершения
function fatal(message: string): never {
console.error('FATAL:', message);
process.exit(1);
}
Never в type guards и exhaustiveness checking
Never используется для проверки того, что все ветви switch обработаны:
type Status = 'success' | 'error' | 'pending';
function handleStatus(status: Status): void {
switch(status) {
case 'success':
console.log('Success!');
break;
case 'error':
console.log('Error!');
break;
case 'pending':
console.log('Pending...');
break;
default:
// Если забыть обработать статус, здесь будет тип never
const exhaustive: never = status; // Ошибка типа!
}
}
// Добавили новый тип
type StatusNew = 'success' | 'error' | 'pending' | 'timeout';
function handleStatusNew(status: StatusNew): void {
switch(status) {
case 'success':
console.log('Success!');
break;
case 'error':
console.log('Error!');
break;
case 'pending':
console.log('Pending...');
break;
// Забыли 'timeout' — здесь TypeScript ошибка!
default:
const exhaustive: never = status; // TS Error!
}
}
Never в условных типах (Conditional Types)
// Удаление null и undefined типов
type NonNullable<T> = T extends null | undefined ? never : T;
type A = NonNullable<string | null>; // string
type B = NonNullable<number | undefined>; // number
type C = NonNullable<null | undefined>; // never
// Фильтрация типов
type FunctionType<T> = T extends (...args: any[]) => any ? T : never;
type IsFn = FunctionType<() => void>; // () => void
type NotFn = FunctionType<string>; // never
Практический пример: обработка ошибок
// Функция с void — обработка без выброса
function logWarning(message: string): void {
console.warn('Warning:', message);
}
// Функция с never — критическая ошибка
function logAndThrow(message: string): never {
console.error('Critical:', message);
throw new Error(message);
}
// Использование
function process(value: any): void {
if (!value) {
logWarning('Value is empty'); // Продолжает работу
}
if (value.id === undefined) {
logAndThrow('ID is required'); // Прерывает программу
}
}
Best Practices
✅ Используй Void:
// Для функций, выполняющих действия
function sendNotification(message: string): void {
// отправляет уведомление
}
// Для обработчиков событий
const onClick = (): void => { /* ... */ };
✅ Используй Never:
// Для функций обработки ошибок
function panic(message: string): never {
throw new Error(message);
}
// Для exhaustiveness checking
default:
const exhaustive: never = unknownValue;
❌ Не путай:
// Плохо: void где нужна never
function badError(): void {
throw new Error('Oops');
}
// Хорошо: never для ошибок
function goodError(): never {
throw new Error('Oops');
}
Суммируя: Void — это тип для функций, которые завершаются нормально и ничего не возвращают. Never — это тип для функций, которые никогда не вернут управление нормально (выброс ошибки, бесконечный цикл). Правильное использование этих типов делает код более безопасным и позволяет TypeScript лучше помогать с проверкой типов.