Типизация API запросов

Основы типизации

В Quasar, как и в любом современном фронтенд-фреймворке на базе Vue.js, важно обеспечить строгую типизацию данных при работе с API. Это повышает безопасность кода, облегчает поддержку и минимизирует ошибки, связанные с неправильной структурой данных. Типизация API запросов достигается сочетанием TypeScript, Axios и интерфейсов для описания формата запросов и ответов.

Интерфейсы для запросов и ответов

Первый шаг — создание интерфейсов, описывающих структуру данных, которые будут отправляться и получаться от сервера:

interface UserRequest {
  name: string;
  email: string;
  password: string;
}

interface UserResponse {
  id: number;
  name: string;
  email: string;
  createdAt: string;
}

Использование таких интерфейсов позволяет TypeScript проверять корректность данных на этапе компиляции. При попытке отправить лишнее поле или получить недостающие данные компилятор выдаст ошибку.

Типизация функций API

Для организации запросов удобно создавать отдельный слой — сервисы API. В Quasar это часто делают через axios или useFetch из @vueuse/core.

import axios, { AxiosResponse } fr om 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000,
});

export const createUser = async (user: UserRequest): Promise<UserResponse> => {
  const response: AxiosResponse<UserResponse> = await apiClient.post('/users', user);
  return response.data;
};

Ключевые моменты:

  • Promise<UserResponse> — гарантирует, что функция вернёт объект строго определённого типа.
  • AxiosResponse<UserResponse> — позволяет использовать возможности Axios для получения метаданных ответа (статус, заголовки) при сохранении строгой типизации данных.

Типизация параметров запроса

Для GET-запросов с параметрами также используется интерфейс:

interface UserQuery {
  page: number;
  lim it: number;
  search?: string;
}

export const getUsers = async (query: UserQuery): Promise<UserResponse[]> => {
  const response: AxiosResponse<UserResponse[]> = await apiClient.get('/users', { params: query });
  return response.data;
};

Типизация параметров позволяет избежать ошибок при формировании URL и гарантирует передачу корректных данных на сервер.

Использование Generics для универсальных функций

Часто создаются универсальные функции для работы с разными сущностями. Для этого применяются generic-типы:

export const fetchData = async <T>(url: string, params?: object): Promise<T> => {
  const response: AxiosResponse<T> = await apiClient.get(url, { params });
  return response.data;
};

// Пример вызова
const users = await fetchData<UserResponse[]>('/users', { page: 1, limit: 10 });

Generic позволяет использовать одну функцию для любых типов данных без потери типизации.

Обработка ошибок с типами

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

interface ApiError {
  message: string;
  code: number;
  details?: string;
}

try {
  const user = await createUser(newUser);
} catch (error: unknown) {
  if (axios.isAxiosError(error) && error.response) {
    const apiError: ApiError = error.response.data;
    console.error(apiError.message);
  }
}

Типизация ошибки гарантирует доступ к правильным полям и предотвращает случайное обращение к несуществующим свойствам.

Интеграция с Quasar Composition API

При использовании Quasar Composition API типизированные функции API можно комбинировать с реактивными переменными и ref:

import { ref } fr om 'vue';

const users = ref<UserResponse[]>([]);
const loading = ref(false);

const loadUsers = async () => {
  loading.value = true;
  try {
    users.value = await getUsers({ page: 1, lim it: 20 });
  } finally {
    loading.value = false;
  }
};

Такой подход обеспечивает строгую типизацию на всех уровнях: реактивные данные, функции API и параметры запроса.

Вывод

Строгая типизация API запросов в Quasar с использованием TypeScript и интерфейсов обеспечивает:

  • защиту от ошибок при передаче данных на сервер;
  • автодополнение и проверку структуры ответа в редакторах кода;
  • единообразие и читаемость кода.

Этот подход особенно эффективен для крупных проектов с множеством API эндпоинтов, где важно гарантировать корректность данных на всех этапах взаимодействия с сервером.