Введение в 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