/** * Чтение ошибки, пришедшей от бэкенда. * * До 02.08.2026 экраны читали её так: `(e as any)?.response?.data?.error` — «неизвестный тип» * в четырёх местах подряд. Опечатка в имени поля при этом не ловилась ничем. * * 🪤 Намеренно НЕ через `axios.isAxiosError`: тесты экранов подсовывают ошибку простым объектом * той же формы (`mockRejectedValue({ response: { data: { error: ... } } })`). Проверка на * настоящую ошибку axios отсекла бы их, и экран вёл бы себя в тестах не так, как в бою. * Читаем форму — она одна и та же в обоих случаях. */ /** Тело ответа с ошибкой — то, что бэкенд кладёт в `data`. */ export interface ApiErrorBody { error?: string; message?: string; errors?: Record; } /** Тело ошибки целиком, либо undefined, если пришло что-то другой формы. */ export function apiErrorBody(error: unknown): ApiErrorBody | undefined { if (typeof error !== 'object' || error === null) return undefined; const response = (error as { response?: unknown }).response; if (typeof response !== 'object' || response === null) return undefined; const data = (response as { data?: unknown }).data; if (typeof data !== 'object' || data === null) return undefined; return data as ApiErrorBody; } /** Код ошибки (`balance_insufficient`, `run_in_flight` и т.п.). */ export function apiErrorCode(error: unknown): string | undefined { return apiErrorBody(error)?.error; } /** Первая ошибка по конкретному полю формы. */ export function apiFieldError(error: unknown, field: string): string | undefined { return apiErrorBody(error)?.errors?.[field]?.[0]; }