Что такое void и never?

В TypeScript наряду с привычными типами вроде string, number или boolean существуют специальные служебные типы, которые помогают описывать поведение функций и выражений. Два таких типа — это void и never. Несмотря на то что они внешне похожи тем, что указывают на отсутствие «нормального» возвращаемого значения, их назначение и использование в коде совершенно разные.

Тип void

void используется в тех случаях, когда функция не возвращает никакого значения. Он прямо указывает, что результат вызова функции не должен использоваться в вычислениях.

Пример:

function logMessage(message: string): void {
console.log(message);
}

Такая функция выполняет действие — выводит сообщение в консоль, — но не возвращает результат. Попытка использовать значение её вызова в выражениях будет бессмысленной.

Особенности void:

  • Он чаще всего применяется для описания сигнатур функций обратного вызова (callback), где возвращаемое значение не имеет значения.

  • В JavaScript функция без return по умолчанию возвращает undefined. В TypeScript же при объявлении void мы явно фиксируем, что возвращаемое значение использоваться не должно, даже если фактически это будет undefined.

Таким образом, void помогает разработчику и компилятору работать более строго и избегать логических ошибок при проектировании API.

Тип never

never указывает на то, что функция или выражение никогда не завершится корректным образом. Это значит, что функция либо всегда выбрасывает исключение, либо зацикливается, и потому возврата значения просто не существует.

Пример функции, возвращающей never:

function throwError(message: string): never {
throw new Error(message);
}

В данном случае выполнение функции прерывается выбросом ошибки, и никакого возвращаемого значения программа не получит.

Другой пример — бесконечный цикл:

function infiniteLoop(): never {
while (true) {
// выполняется бесконечно
}
}

Особенности never:

  • Этот тип нужен для описания «невозможных ситуаций» в коде.

  • Он часто используется в конструкциях с исчерпывающим перечислением вариантов, например при работе с switch, чтобы убедиться, что обработаны все возможные случаи.

Пример проверки всех значений перечисления:

type Shape = "circle" | "square";
function getArea(shape: Shape): number {
switch (shape) {
case "circle":
return Math.PI \* 10 \* 10;
case "square":
return 100;
default:
const \_exhaustiveCheck: never = shape;
return \_exhaustiveCheck;
}
}

Здесь never гарантирует, что если в будущем в Shape добавится новое значение, компилятор заставит разработчика его обработать.

Сравнение void и never

  1. Смысл:

    • void означает отсутствие возвращаемого значения, но функция завершает выполнение.

    • never означает невозможность завершения функции корректным образом.

  2. Использование:

    • void используется в функциях, которые что-то делают, но не возвращают результата.

    • never используется для функций, которые либо всегда выбрасывают исключение, либо зацикливаются.

  3. Типизация:

    • void можно рассматривать как «разрешённый, но пустой» результат.

    • never показывает «невозможность результата» как такового.