Как корректно указывать типы для результатов выполнения функций, которые завершились с ошибкой?

У меня есть следующая функция: <br/> <br/> <pre><code class="typescript">export const usersPassportLogin = async (
  usersPassportLoginBody: UsersPassportLoginBody,
  options?: RequestInit
): Promise&lt;usersPassportLoginResponse&gt; =&gt; {
  return customFetch&lt;Promise&lt;usersPassportLoginResponse&gt;&gt;(getUsersPassportLoginUrl(), {
    ...options,
    method: 'POST',
    headers: { 'Content-Type': 'application/json', ...options?.headers },
    body: JSON.stringify(usersPassportLoginBody)
  });
};</code></pre> <br/> <br/> Эта функция возвращает промис, определяемый следующим образом: <br/> <pre><code class="typescript">export type usersPassportLoginResponse = {
  data: UsersPassportLogin200;
  status: number;
};</code></pre> <br/> <br/> В случае ошибки функция возвращает ValidationError, который определен так: <br/> <pre><code class="typescript">export interface ValidationError {
  errors: ValidationErrorErrors;
  message: string;
}</code></pre> <br/> <br/> Я не могу изменить исходную функцию, но как мне обработать ошибку, чтобы ловить ValidationError, учитывая что в исходном ответе нет поля errors?
  • 14 октября 2024 г. 14:13
Ответы на вопрос 2
Чтобы корректно обрабатывать ошибки, такие как `ValidationError`, в функции `usersPassportLogin`, необходимо использовать подход, при котором ошибка будет выбрасываться или обрабатываться через `Promise`. Поскольку вы не можете изменить исходную функцию, вы можете обернуть её вызов в `try-catch` блок и возвращать ошибку, если она произошла.

Вот пример, как вы можете это реализовать:

```typescript
export const usersPassportLogin = async (
  usersPassportLoginBody: UsersPassportLoginBody,
  options?: RequestInit
): Promise<usersPassportLoginResponse | ValidationError> => {
  try {
    const response = await customFetch<Promise<usersPassportLoginResponse>>(getUsersPassportLoginUrl(), {
      ...options,
      method: 'POST',
      headers: { 'Content-Type': 'application/json', ...options?.headers },
      body: JSON.stringify(usersPassportLoginBody)
    });

    // Проверяем статус ответа и предположим, что статус ошибок (< 200 или >= 400)
    if (!response || (response.status < 200 || response.status >= 300)) {
      throw new ValidationError({
        errors: response.errors || {}, // Замените на нужное значение по обработке ошибок
        message: 'Validation error occurred'
      });
    }

    return response;
  } catch (error) {
    if (isValidationError(error)) {
      return error; // Возвращаем ValidationError
    }
    // Обработка других типов ошибок, если это необходимо
    throw error; // Или можно обернуть в другой тип ошибки
  }
};

// Псевдокод для определения, является ли ошибка ValidationError
function isValidationError(error: any): error is ValidationError {
  return error && typeof error.message === 'string' && error.errors !== undefined;
}

// Вызов функции
(async () => {
  const result = await usersPassportLogin(usersPassportLoginBody);
  if ('errors' in result) {
    // Обработка ValidationError
    console.error('Validation errors:', result.errors);
  } else {
    // Обработка успешного результата
    console.log('Login successful:', result);
  }
})();
```

### Объяснение:

1. **Возврат различных типов**: Функция может возвращать как `usersPassportLoginResponse`, так и `ValidationError`, поэтому мы указываем это в типе возвращаемого значения: `Promise<usersPassportLoginResponse | ValidationError>`.

2. **Проверка статуса ответа**: Внутри блока `try` мы можем проверить статус ответа и выбросить `ValidationError`, если статус указывает на ошибку. 

3. **Обработка ошибок с помощью `catch`**: В блоке `catch` мы проверяем, является ли пойманная ошибка `ValidationError`. Если это так, мы возвращаем её. В противном случае можно либо пробросить ошибку дальше, либо обрабатывать её другим способом.

4. **Функция `isValidationError`**: Это типовая защитная функция, которая проверяет, является ли ошибка объектом `ValidationError`.

Таким образом, вы сможете корректно обрабатывать ошибки и различать成功ные результаты и ошибки в вашем коде.
В такой ситуации, когда ты не можешь менять исходную функцию, но хочешь обрабатывать ошибки, можно сделать дополнительный слой обработки в месте, где вызывается функция. Ты можешь использовать try-catch, чтобы перехватывать исключения и обрабатывать их как ValidationError. Вот пример: 

try {
  const response = await usersPassportLogin(usersPassportLoginBody, options);
  // Успешный ответ обрабатывай как обычно
  console.log('Login successful:', response);
} catch (error) {
  // Здесь мы проверим, является ли ошибка ValidationError
  if ((error as ValidationError).errors) {
    const validationError = error as ValidationError;
    console.log('Validation Error:', validationError.errors);
  } else {
    console.log('Unexpected Error:', error);
  }
}
Похожие вопросы