Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Never тип — типизация функций, которые никогда не возвращают значение
Never — это специальный тип в TypeScript, который указывает, что функция никогда не вернёт нормальное значение. Функция может либо выбросить ошибку, либо работать бесконечно.
Когда используется Never
// Функция выбрасывает исключение
function throwError(message: string): never {
throw new Error(message);
}
// Функция работает бесконечно
function infiniteLoop(): never {
while (true) {
// Бесконечный цикл
}
}
// Функция никогда не достигает конца
function assertNever(x: never): never {
throw new Error(`Unreachable code: ${x}`);
}
Never vs Void
// ❌ Void — функция возвращает undefined
function log(message: string): void {
console.log(message);
return; // Возвращает undefined
}
const result1: undefined = log("Hello"); // Ошибка в TypeScript
// На самом деле log возвращает undefined
// ✅ Never — функция никогда не возвращает
function throwError(message: string): never {
throw new Error(message); // Никогда не вернёт, даже undefined
}
const result2: never = throwError("Error"); // Никогда не достигнет этой строки
Практический пример: Exhaustiveness checking
type Status = "loading" | "success" | "error";
function handleStatus(status: Status): string {
switch (status) {
case "loading":
return "Загружаем...";
case "success":
return "Готово!";
case "error":
return "Ошибка!";
default:
// ✅ TypeScript покажет ошибку если забыли обработать статус
const _exhaustiveCheck: never = status;
return _exhaustiveCheck;
}
}
// Если добавить новый статус, TypeScript покажет ошибку
type NewStatus = "loading" | "success" | "error" | "pending";
function handleNewStatus(status: NewStatus): string {
switch (status) {
case "loading":
return "Загружаем...";
case "success":
return "Готово!";
case "error":
return "Ошибка!";
case "pending":
return "В ожидании...";
default:
// ✅ Если забыли обработать "pending", ошибка уже здесь
const _exhaustiveCheck: never = status;
return _exhaustiveCheck;
}
}
Never в объединённых типах (Union Types)
// Never удаляется из объединения
type A = string | never; // Результат: string
type B = number | never; // Результат: number
type C = never | "a" | "b"; // Результат: "a" | "b"
// Это полезно для условных типов
type Exclude<T, U> = T extends U ? never : T;
type NoString = Exclude<string | number | boolean, string>;
// Результат: number | boolean
// (string исключён, потому что вернёт never, который удаляется)
type NoFunction = Exclude<string | (() => void), Function>;
// Результат: string
// (функция исключена)
Использование Never для невозможных случаев
// Функция что-то на основе типа
function processValue(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
} else if (typeof value === "number") {
return value.toString();
} else {
// Это место никогда не должно быть достигнуто
const _unreachable: never = value;
throw new Error(`Unreachable: ${_unreachable}`);
}
}
// React компонент с невозможными props
interface SuccessProps {
type: "success";
message: string;
}
interface ErrorProps {
type: "error";
error: Error;
}
type MessageProps = SuccessProps | ErrorProps;
function Message(props: MessageProps) {
switch (props.type) {
case "success":
return <div>{props.message}</div>;
case "error":
return <div>Ошибка: {props.error.message}</div>;
default:
// Если типы обновлены, но обработчик забыли
const _exhaustive: never = props;
return _exhaustive;
}
}
Never для функций обработки ошибок
// Функция, которая ВСЕГДА выбрасывает ошибку
function invariant(condition: any, message: string): asserts condition {
if (!condition) {
throw new Error(message);
}
}
function parseNumber(value: string): number {
const num = parseInt(value, 10);
invariant(!isNaN(num), `Invalid number: ${value}`);
// После проверки компилятор знает, что num — это number
return num;
}
// Функция обработки ошибок (никогда не возвращает)
function handleError(error: Error): never {
console.error(error);
process.exit(1);
}
// API call с обработкой ошибок
async function fetchUser(id: number): Promise<User> {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
handleError(new Error(`HTTP ${response.status}`));
}
return response.json();
} catch (error) {
handleError(error as Error);
}
}
Never в условных типах
// Полезно для построения сложных типов
type IsAny<T> = unknown extends T ? (T extends any ? true : false) : false;
type TrueIfAny<T> = T extends never ? false : true;
// Получить ключи объекта, значение которых — функция
type FunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends (...args: any[]) => any ? K : never;
}[keyof T];
interface MyObject {
name: string;
greet: () => void;
count: number;
calculate: (a: number) => number;
}
type FuncKeys = FunctionPropertyNames<MyObject>;
// Результат: "greet" | "calculate"
Never в Generic типах
// Создаём тип, который исключает undefined
type NonUndefined<T> = T extends undefined ? never : T;
type StringOrUndefined = NonUndefined<string | undefined>;
// Результат: string
type NeverType = NonUndefined<undefined>;
// Результат: never
// Практический пример: требуемые поля в форме
type FormField<T> = {
value: T;
error?: string;
};
type RequiredFields<T> = {
[K in keyof T]: T[K] extends undefined ? never : FormField<T[K]>;
};
interface UserForm {
name?: string;
email?: string;
age: number;
}
type ValidUserForm = RequiredFields<UserForm>;
// Только age будет типизирован как FormField
Важные замечания
// ✅ Never можно использовать как значение return type
function stopExecution(): never {
throw new Error("Stop here");
}
// ❌ Нельзя создать переменную типа never
const x: never = "something"; // Ошибка!
// ✅ Но можно в типе
type ImpossibleType = {
value: never;
};
// Если функция имеет return type never, она ДОЛЖНА выбросить или зависнуть
function badNever(): never {
return undefined; // ❌ Ошибка компиляции
}
// ✅ Правильно
function goodNever(): never {
throw new Error("Must throw");
}