Что такое Never

В языке программирования Dart тип Never представляет собой специальный тип, который указывает, что функция или выражение никогда не завершится успешно и никогда не вернёт управление. Это означает, что код либо завершает выполнение с ошибкой, либо зацикливается бесконечно, либо завершает выполнение программы.

📌 Основные характеристики типа Never

  1. Never — это подтип всех типов (bottom type):

    • Это означает, что значение типа Never можно подставить вместо любого другого типа, потому что оно никогда не существует.

    • Используется, когда выполнение кода никогда не дойдёт до этой точки.

  2. Never — это тип, который нельзя инстанцировать:

    • Нельзя создать переменную типа Never, потому что не существует значения этого типа.

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

🧠 Когда и зачем используется Never

1. Функции, которые выбрасывают исключения

Never throwError(String message) {
throw Exception(message);
}
  • Функция возвращает Never, потому что она никогда не завершится успешно — она сразу бросает исключение.

  • Это помогает компилятору и анализатору Dart понять, что после вызова этой функции выполнение не продолжится.

2. Функции с бесконечным циклом

Never infiniteLoop() {
while (true) {
// бесконечный цикл
}
}
  • Такая функция никогда не возвращает, и тип Never делает это явным.

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

3. Оператор switch с исчерпывающим перечислением (exhaustive switch)

Если вы используете sealed class или enum, Dart может потребовать указания всех возможных вариантов. Если один из case завершает выполнение с исключением, можно указать Never, чтобы Dart понял, что это корректно.

enum ShapeType { circle, square }
String shapeName(ShapeType type) {
switch (type) {
case ShapeType.circle:
return "Circle";
case ShapeType.square:
throw UnimplementedError("Square not yet supported");
}
}

В таком случае throw возвращает Never, и Dart понимает, что ветка не завершится успешно, даже если значение square не возвращает строку.

4. Типизация с ! (non-null assertion operator)

Тип Never также играет роль при использовании !, например:

String? maybeStr;
print(maybeStr!); // Если maybeStr == null, будет выброшено исключение

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

🔬 Never vs Null vs void

Тип Назначение Может быть возвращён?
void Означает отсутствие возвращаемого значения (но функция завершается) ✅ Да
--- --- ---
Null Единственный допустимый тип, содержащий null ✅ Да
--- --- ---
Never Означает, что функция не завершится нормально и не вернёт ничего ❌ Нет
--- --- ---

📚 Примеры использования Never в реальных проектах

  • В assert или throw: явно указывая, что после этого кода выполнение не продолжится.

  • При проверке ошибок: если функция должна прервать выполнение при неразрешимом состоянии.

  • В функциональных паттернах (например, Result / Either), где неуспешные ветви можно завершить через Never.

Пример в стиле функционального программирования:

Either<Error, Data> fetchData();
void processData() {
final result = fetchData();
result.fold(
(error) => throwError(error.message), // Возвращает Never
(data) => print(data),
);
}

🧩 Роль Never в системе типов Dart

Dart — это язык с строгой типизацией, и Never играет важную роль:

  • Повышает безопасность типов.

  • Позволяет компилятору анализировать контроль потока (control flow analysis).

  • Улучшает анализатор кода: он может предупреждать об unreachable code, dead code и забытых return.

Таким образом, Never — это фундаментальный элемент системы типов Dart, предназначенный для описания ситуаций, в которых выполнение кода гарантированно не завершится успешно и не вернёт управление.