Introducción a GraphQL API con TypeScript
GraphQL es un lenguaje de consultas moderno para APIs que permite a los clientes solicitar únicamente los datos que realmente necesitan. En combinación con TypeScript, que añade tipado estricto, el desarrollo se vuelve más predecible y seguro. En este tutorial paso a paso crearemos una API completa de GraphQL en TypeScript, utilizando herramientas populares y mejores prácticas.
¿Por qué elegir GraphQL con TypeScript? En primer lugar, obtienes autocompletado y verificación de tipos en tiempo de compilación. En segundo lugar, GraphQL permite combinar múltiples consultas en una sola, reduciendo la cantidad de solicitudes de red. En tercer lugar, TypeScript es ideal para describir estructuras de datos de grafos complejas.
Configuración del proyecto e instalación de dependencias
Para empezar, crearemos un nuevo proyecto e instalaremos los paquetes necesarios. Usaremos Apollo Server, el servidor más popular para GraphQL, y TypeGraphQL para una integración sencilla con TypeScript.
mkdir graphql-ts-tutorialcd graphql-ts-tutorialnpm init -ynpm install apollo-server graphql reflect-metadata class-validatornpm install typescript type-graphql @types/node --save-devnpx tsc --initDespués de la instalación, configuraremos tsconfig.json. Asegúrate de que las siguientes opciones estén incluidas:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": ["ES2020"], "experimentalDecorators": true, "emitDecoratorMetadata": true, "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true }}Crearemos la estructura de carpetas:
src/ ├── index.ts ├── resolvers/ │ └── user.resolver.ts ├── schemas/ │ └── user.schema.ts └── data/ └── users.tsCreación del esquema y tipos de datos
En TypeGraphQL, los tipos de datos se describen mediante decoradores. Crearemos un modelo de usuario y un tipo de datos de entrada para la mutación.
// src/schemas/user.schema.tsimport { 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;}Observa el uso de @ObjectType() para describir los tipos de retorno y @InputType() para los parámetros de entrada. Esto permite que TypeGraphQL genere automáticamente el esquema de GraphQL.
Implementación de resolvers
Los resolvers son funciones que procesan las consultas y devuelven datos. Crearemos un array simple en memoria para almacenar usuarios.
// src/data/users.tsimport { User } from "../schemas/user.schema";
export const users: User[] = [ { id: 1, name: "Iván Petrov", email: "ivan@example.com", age: 28 }, { id: 2, name: "María Sidorova", email: "maria@example.com", age: 32 },];Ahora escribiremos los resolvers para consultas y mutaciones:
// src/resolvers/user.resolver.tsimport { 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 =