API GraphQL com TypeScript: tutorial passo a passo
GraphQL é uma linguagem de consulta para APIs que permite aos clientes solicitar apenas os dados de que precisam. Em combinação com TypeScript, a tipagem estática ajuda a evitar erros durante o desenvolvimento e torna o código mais previsível. Neste tutorial, criaremos uma API GraphQL completa usando Apollo Server e TypeScript.
Abordaremos: configuração do projeto, definição do schema e tipos, implementação de resolvers, mutações para alterar dados e integração com banco de dados (in-memory para simplificar). Ao final do artigo, você poderá executar seu próprio servidor GraphQL.
1. Preparação do projeto e instalação de dependências
Primeiro, criaremos um novo projeto Node.js e instalaremos os pacotes necessários.
mkdir graphql-typescript-tutorialcd graphql-typescript-tutorialnpm init -ynpm install apollo-server graphqlnpm install -D typescript @types/node ts-node nodemonCriaremos o arquivo tsconfig.json:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "rootDir": "./src", "outDir": "./dist", "strict": true, "esModuleInterop": true, "skipLibCheck": true }, "include": ["src/**/*"]}A estrutura do projeto será a seguinte:
src/index.ts— ponto de entradasrc/schema.ts— schema GraphQLsrc/resolvers.ts— resolverssrc/types.ts— tipos TypeScript
2. Definição de tipos e schema GraphQL
O schema GraphQL descreve quais dados estão disponíveis e como solicitá-los. Como exemplo, criaremos um sistema simples de gerenciamento de usuários e posts.
Criaremos src/types.ts:
export interface User { id: number; name: string; email: string;}
export interface Post { id: number; title: string; content: string; authorId: number;}
export interface CreateUserInput { name: string; email: string;}
export interface CreatePostInput { title: string; content: string; authorId: number;}Agora criaremos src/schema.ts com a definição dos tipos GraphQL:
import { gql } from 'apollo-server';
export const typeDefs = gql` type User { id: ID! name: String! email: String! posts: [Post!]! }
type Post { id: ID! title: String! content: String! author: User! }
input CreateUserInput { name: String! email: String! }
input CreatePostInput { title: String! content: String! authorId: ID! }
type Query { users: [User!]! user(id: ID!): User posts: [Post!]! post(id: ID!): Post }
type Mutation { createUser(input: CreateUserInput!): User! createPost(input: CreatePostInput!): Post! }`;Observe: usamos tipos input para mutações — esta é uma prática padrão em GraphQL.
3. Implementação de resolvers com TypeScript
Resolvers são funções que retornam dados para cada campo do schema. Criaremos src/resolvers.ts:
import { User, Post, CreateUserInput, CreatePostInput } from './types';
// Banco de dados in-memorylet users: User[] = [ { id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob', email: 'bob@example.com' },];
let posts: Post[] = [ { id: 1, title: 'GraphQL Basics', content: '...', authorId: 1 }, { id: 2, title: 'TypeScript Guide', content: '...', authorId: 2 },];
let nextUserId = 3;let nextPostId = 3;
export const resolvers = { Query: { users: (): User[] => users, user: (_: unknown, args: { id: string }): User | undefined => users.find(u => u.id === Number(args.id)), posts: (): Post[] => posts, post: (_: unknown,