GraphQL API с TypeScript: пошаговый туториал для разработчиков

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в GraphQL API с TypeScript

GraphQL — это современный язык запросов для API, который позволяет клиентам запрашивать только те данные, которые им действительно нужны. В сочетании с TypeScript, который добавляет строгую типизацию, разработка становится более предсказуемой и безопасной. В этом пошаговом туториале мы создадим полноценный GraphQL API на TypeScript, используя популярные инструменты и лучшие практики.

Почему стоит выбрать GraphQL с TypeScript? Во-первых, вы получаете автодополнение и проверку типов на этапе компиляции. Во-вторых, GraphQL позволяет объединять несколько запросов в один, уменьшая количество сетевых запросов. В-третьих, TypeScript идеально подходит для описания сложных графовых структур данных.

Настройка проекта и установка зависимостей

Для начала создадим новый проект и установим необходимые пакеты. Мы будем использовать Apollo Server — самый популярный сервер для GraphQL, и TypeGraphQL для удобной интеграции с TypeScript.

mkdir graphql-ts-tutorial
cd graphql-ts-tutorial
npm init -y
npm install apollo-server graphql reflect-metadata class-validator
npm install typescript type-graphql @types/node --save-dev
npx tsc --init

После установки настроим tsconfig.json. Убедитесь, что включены следующие опции:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "lib": ["ES2020"],
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true
  }
}

Создадим структуру папок:

src/
  ├── index.ts
  ├── resolvers/
  │   └── user.resolver.ts
  ├── schemas/
  │   └── user.schema.ts
  └── data/
      └── users.ts

Создание схемы и типов данных

В TypeGraphQL типы данных описываются с помощью декораторов. Создадим модель пользователя и тип входных данных для мутации.

// src/schemas/user.schema.ts
import { ObjectType, Field, ID, InputType } from "type-graphql";

@ObjectType()
export class User {
  @Field(() => ID)
  id!: number;

  @Field()
  name!: string;

  @Field()
  email!: string;

  @Field({ nullable: true })
  age?: number;
}

@InputType()
export class CreateUserInput {
  @Field()
  name!: string;

  @Field()
  email!: string;

  @Field({ nullable: true })
  age?: number;
}

Обратите внимание на использование @ObjectType() для описания возвращаемых типов и @InputType() для входных параметров. Это позволяет TypeGraphQL автоматически генерировать GraphQL-схему.

Реализация резолверов

Резолверы — это функции, которые обрабатывают запросы и возвращают данные. Создадим простой in-memory массив для хранения пользователей.

// src/data/users.ts
import { User } from "../schemas/user.schema";

export const users: User[] = [
  { id: 1, name: "Иван Петров", email: "ivan@example.com", age: 28 },
  { id: 2, name: "Мария Сидорова", email: "maria@example.com", age: 32 },
];

Теперь напишем резолверы для запросов и мутаций:

// src/resolvers/user.resolver.ts
import { Resolver, Query, Mutation, Arg, Int } from "type-graphql";
import { User, CreateUserInput } from "../schemas/user.schema";
import { users } from "../data/users";

@Resolver()
export class UserResolver {
  @Query(() => [User])
  async getAllUsers(): Promise<User[]> {
    return users;
  }

  @Query(() => User, { nullable: true })
  async getUserById(
    @Arg("id", () => Int) id: number
  ): Promise<User | undefined> {
    return users.find(user => user.id === id);
  }

  @Mutation(() => User)
  async createUser(
    @Arg("input") input: CreateUserInput
  ): Promise<User> {
    const newUser: User = {
      id: users.length + 1,
      ...input,
    };
    users.push(newUser);
    return newUser;
  }
}

Декораторы @Query и @Mutation указывают тип операции. @Arg используется для привязки аргументов запроса к параметрам функции. TypeGraphQL автоматически валидирует типы на основе декораторов.

Настройка сервера и запуск

Соберём всё вместе в главном файле index.ts:

// src/index.ts
import "reflect-metadata";
import { ApolloServer } from "apollo-server";
import { buildSchema } from "type-graphql";
import { UserResolver } from "./resolvers/user.resolver";

async function startServer() {
  const schema = await buildSchema({
    resolvers: [UserResolver],
    emitSchemaFile: true, // генерирует schema.graphql
  });

  const server = new ApolloServer({
    schema,
    playground: true, // включает GraphQL Playground для тестирования
  });

  const { url } = await server.listen(4000);
  console.log(`🚀 Сервер запущен на ${url}`);
}

startServer().catch(console.error);

После запуска (npx ts-node src/index.ts) сервер будет доступен по адресу http://localhost:4000/graphql. Откройте GraphQL Playground и выполните тестовый запрос:

query {
  getAllUsers {
    id
    name
    email
    age
  }
}

Вы должны получить список всех пользователей. Попробуйте мутацию для создания нового пользователя:

mutation {
  createUser(input: {
    name: "Алексей Кузнецов"
    email: "alex@example.com"
    age: 25
  }) {
    id
    name
    email
  }
}

Расширение функциональности

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

  • Пагинация — добавьте аргументы skip и take в запрос getAllUsers
  • Фильтрация — реализуйте поиск пользователей по имени или email
  • Валидация — используйте class-validator для проверки email формата
  • Подписки — добавьте real-time обновления через WebSocket

Пример добавления пагинации:

@Query                

Блоги

Рекомендаций по книгам