ПрограммированиеFullstack разработчик

Поясните разницу между типом never и void в TypeScript. Когда и зачем стоит использовать каждый из них?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

void и never в TypeScript — разные типы:

  • void обычно используется как возвращаемый тип для функций, которые ничего не возвращают, т.е. функция завершает выполнение, но не возвращает значение.
  • never означает, что функция (или выражение) никогда не завершится успешно: либо всегда выбрасывает исключение, либо никогда не возвращает управление (например, бесконечный цикл).

Примеры:

function log(message: string): void { console.log(message); } function throwError(message: string): never { throw new Error(message); } function infinite(): never { while (true) {} }

never часто используется для контроля полноты switch-case по типам:

type Shape = { kind: 'circle' } | { kind: 'square' }; function getArea(shape: Shape) { switch (shape.kind) { case 'circle': return 1; case 'square': return 2; default: const _exhaustive: never = shape; // Тут компилятор подскажет, если пропущен кейс } }

Вопрос с подвохом.

Могут ли void и never использоваться взаимозаменяемо как возвращаемые типы функции?

Ответ: Нет. Функция с типом void возвращает undefined либо ничего не возвращает, но завершает выполнение. Функция с типом never никогда не завершает выполнение успешно (кидает ошибку либо уходит в бесконечный цикл).

Пример:

const fn: () => never = () => { // return; // Ошибка: A function whose declared type is 'never' must not return. };

История

В аналитической системе функцию-валидатор типизировали с возвращаемым типом void, хотя она всегда выбрасывала исключение. В результате разработчики считали, что функция может "вернуться", и не ставили дальнейшие проверки, из-за чего пропустили обработку ошибок и неправильно реализовали цепочку вызовов.


История

В одном из проектов TypeScript-функцию, ожидающую чётко типизированный возвращаемый тип, определили как возвращающую never, а не void. Из-за этого попытка вызвать функцию с колбэком, который был типизирован как never, привела к ошибкам компиляции и потери совместимости API.


История

В backend-модуле раньше выводили исключение через функцию с возвращаемым типом void. После миграции на TypeScript компилятор не предупреждал о выходе за пределы кода после вызова этой функции, что привело к лишним строчкам "невыполнимого" кода — и только изменение возвращаемого типа на never позволило обнаружить такие места и сделать код чище, избежав логической ошибки.