Типизация запросов с помощью Apollo Codegen (а ещё немного магии)
Для начала, мы научимся генерировать типы для наших запросов. Хорошая новость: нам не нужно вручную выписывать все возможные структуры данных! Мы будем использовать библиотеку Apollo Codegen.
Установка Apollo Codegen
Для начала убедимся, что в нашем проекте уже установлен Apollo Client. Если нет, установите его из предыдущей лекции:
npm install @apollo/client graphql
Теперь можно установить инструменты для генерации типов:
npm install -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations
Настройка конфигурации Codegen
Создайте новый файл codegen.yml в корне проекта. Это конфигурация для генератора типов. Вот пример содержимого:
overwrite: true
schema: "https://YOUR_GRAPHQL_API_URL" # Замените на ваш GraphQL эндпоинт
documents: "src/**/*.graphql" # Укажите путь к вашим GraphQL-запросам
generates:
src/__generated__/types.ts:
plugins:
- "typescript"
- "typescript-operations"
Что здесь происходит:
- schema — ссылка на ваш GraphQL API (вы можете также использовать файл
.graphqlс локальной схемой). - documents — путь к файлам с вашими GraphQL-запросами.
- generates — настройка генерируемого файла, куда будут записываться типы.
Запустите генерацию типов с помощью команды:
npx graphql-codegen
Если всё прошло успешно, вы увидите файл src/__generated__/types.ts с типами для всех ваших GraphQL-запросов и мутаций. Ура! Теперь у нас есть типы, соответствующие API.
Пример: Типизация запроса useQuery
Мы сгенерировали типы, но как их использовать? Давайте рассмотрим, как типизировать базовый запрос.
Создайте файл queries.graphql (или используйте уже существующий). Добавим запрос для получения информации о пользователях:
query GetUsers {
users {
id
name
email
}
}
Теперь, когда у нас есть запрос, после запуска graphql-codegen, в types.ts будет сгенерирован следующий тип:
export type GetUsersQuery = {
users: Array<{
id: string;
name: string;
email: string;
}>;
};
Интеграция типов в useQuery
Используем сгенерированные типы в нашем React-компоненте:
import React from "react";
import { useQuery, gql } from "@apollo/client";
import { GetUsersQuery } from "./__generated__/types";
// GraphQL-запрос
const GET_USERS = gql`
query GetUsers {
users {
id
name
email
}
}
`;
const UsersList: React.FC = () => {
// Используем типизацию для данных и ошибок
const { data, loading, error } = useQuery<GetUsersQuery>(GET_USERS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;
// Гарантировано, что `data.users` существует и имеет правильный тип
return (
<ul>
{data?.users.map((user) => (
<li key={user.id}>
{user.name} ({user.email})
</li>
))}
</ul>
);
};
export default UsersList;
Здесь мы типизировали данные, возвращаемые из useQuery. Теперь, если мы попытаемся обратиться к несуществующему полю (например, user.age), TypeScript сразу выдаст ошибку.
Ручное создание типов (если вы смелый разработчик)
Не всегда есть возможность (или желание) использовать Apollo Codegen. Иногда вам может потребоваться определить типы вручную.
Вот как можно типизировать наш запрос вручную:
// Типизация данных
type User = {
id: string;
name: string;
email: string;
};
type GetUsersQuery = {
users: User[];
};
И затем передать эти типы в useQuery:
const { data, loading, error } = useQuery<GetUsersQuery>(GET_USERS);
Хотя этот метод работает, он не так надёжен, так как вы рискуете случайно ввести неверные типы, которые не совпадают с API.
Советы и рекомендации
- Используйте Codegen — это избавит вас от необходимости отслеживать изменения схемы вручную.
- Выделяйте время на настройку типов — это экономит кучу времени в долгосрочной перспективе.
- Проверяйте типы при изменениях API — всегда регенерируйте типы при обновлении GraphQL-схемы.
- Типизируйте ошибки — ошибки в GraphQL также можно типизировать, чтобы их обработка была более предсказуемой.
Практическое применение в реальной жизни
На собеседованиях часто спрашивают про типизацию GraphQL-запросов, так как это демонстрирует вашу внимательность к деталям и умение писать предсказуемый и надёжный код. В реальных проектах типизация поможет вашей команде быстрее понимать код и избежать множества багов, связанных с неверными данными.
Также, использование Codegen особенно полезно в крупных проектах с большим количеством запросов и мутаций, где ручное управление типами становится неуправляемым.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ