GraphQL API с TypeScript: пошаговый туториал на практике

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

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

Начать курс

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

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

Это руководство подойдет разработчикам, знакомым с основами JavaScript и Node.js. Мы пройдем путь от установки зависимостей до тестирования готового API.

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

Первым делом создадим новый проект и установим необходимые пакеты. Откройте терминал и выполните:

mkdir graphql-ts-tutorial
cd graphql-ts-tutorial
npm init -y

Установите TypeScript, Apollo Server и GraphQL:

npm install apollo-server graphql
npm install -D typescript @types/node ts-node nodemon

Создайте файл tsconfig.json для конфигурации TypeScript:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "rootDir": "./src",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}

Создайте папку src и файл src/index.ts — это будет точка входа в наше приложение.

2. Создание схемы GraphQL и типов TypeScript

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

Файл src/schema.ts:

import { gql } from 'apollo-server';

export const typeDefs = gql`
  type Book {
    id: ID!
    title: String!
    author: String!
    publishedYear: Int
  }

  type Query {
    books: [Book]
    book(id: ID!): Book
  }

  type Mutation {
    addBook(title: String!, author: String!, publishedYear: Int): Book
    deleteBook(id: ID!): Book
  }
`;

Теперь определим TypeScript-интерфейсы для наших данных. Создайте src/types.ts:

export interface Book {
  id: string;
  title: string;
  author: string;
  publishedYear?: number;
}

Обратите внимание: TypeScript интерфейсы нужны для внутренней логики, а GraphQL типы — для клиент-серверного взаимодействия. Они должны быть согласованы.

3. Реализация резолверов и сервера

Резолверы — это функции, которые возвращают данные для каждого поля схемы. Создадим файл src/resolvers.ts с имитацией базы данных:

import { Book } from './types';

let books: Book[] = [
  { id: '1', title: 'Война и мир', author: 'Лев Толстой', publishedYear: 1869 },
  { id: '2', title: 'Преступление и наказание', author: 'Фёдор Достоевский', publishedYear: 1866 },
];

export const resolvers = {
  Query: {
    books: (): Book[] => books,
    book: (_: any, args: { id: string }): Book | undefined => {
      return books.find(book => book.id === args.id);
    },
  },
  Mutation: {
    addBook: (_: any, args: { title: string; author: string; publishedYear?: number }): Book => {
      const newBook: Book = {
        id: String(books.length + 1),
        title: args.title,
        author: args.author,
        publishedYear: args.publishedYear,
      };
      books.push(newBook);
      return newBook;
    },
    deleteBook: (_: any, args: { id: string }): Book | null => {
      const index = books.findIndex(book => book.id === args.id);
      if (index === -1) return null;
      const deletedBook = books.splice(index, 1)[0];
      return deletedBook;
    },
  },
};

Теперь соединим все в главном файле src/index.ts:

import { ApolloServer } from 'apollo-server';
import { typeDefs } from './schema';
import { resolvers } from './resolvers';

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`🚀 Сервер запущен по адресу: ${url}`);
});

Добавьте скрипт запуска в package.json:

"scripts": {
  "start": "ts-node src/index.ts",
  "dev": "nodemon --exec ts-node src/index.ts"
}

Запустите сервер командой npm run dev и перейдите в браузере по адресу http://localhost:4000. Вы увидите GraphQL Playground, где сможете тестировать запросы.

4. Тестирование API и практические примеры

Откройте GraphQL Playground и выполните несколько запросов.

Пример 1: Получить все книги

query {
  books {
    id
    title
    author
  }
}

Ответ:

{
  "data": {
    "books": [
      { "id": "1", "title": "Война и мир", "author": "Лев Толстой" },
      { "id": "2", "title": "Преступление и наказание", "author": "Фёдор Достоевский" }
    ]
  }
}

Пример 2: Добавить новую книгу

mutation {
  addBook(title: "Мастер и Маргарита", author: "Михаил Булгаков", publishedYear: 1967) {
    id
    title
  }
}

Пример 3: Получить одну книгу по ID

query {
  book(id: "3") {
    title
    author
    publishedYear
  }
}

Обратите внимание на гибкость GraphQL: вы можете запрашивать только нужные поля (например, только title и author), и сервер вернет ровно то, что запрошено. Это ключевое преимущество перед REST API.

Заключение

Мы создали работающий GraphQL API на TypeScript с нуля. В этом туториале вы научились:

  • Настраивать проект с TypeScript и Apollo Server
  • Определять GraphQL-схему и TypeScript-типы
  • Реализовывать резолверы для Query и Mutation
  • Тестировать API через GraphQL Playground

Блоги

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