GraphQL vs REST en TypeScript: ¿duelo de titanes o elección según la tarea?
\n\nCuando escribes en TypeScript, la cuestión de la arquitectura del backend se vuelve especialmente crítica. No solo quieres "que funcione", sino que los tipos vuelen, los errores se detecten en tiempo de compilación y el código sea predecible. Y aquí el desarrollador se enfrenta a la elección eterna: ¿el probado REST o el moderno y flexible GraphQL? Ambas tecnologías se llevan muy bien con TypeScript, pero cada una dicta su propio estilo de desarrollo.
\n\nEn este artículo no divagaremos ni contaremos verdades absolutas. Analizaremos GraphQL vs REST en TypeScript con ejemplos concretos, código, puntos débiles y escenarios donde un enfoque supera al otro. ¡Allá vamos!
\n\nREST: el viejo amigo que nunca falla
\n\nREST (Transferencia de Estado Representacional) es un estilo arquitectónico donde cada recurso (usuario, publicación, comentario) tiene su propia URL. Accedes a /api/users/1 y obtienes el usuario. Simple y predecible. En proyectos TypeScript, REST se implementa a menudo con Express, Fastify o NestJS.
Tipado en REST con TypeScript
\nEl principal dolor de REST es la débil conexión entre el backend y el frontend. Envías JSON y el frontend adivina: "¿Y qué llegó?". TypeScript lo soluciona mediante tipos compartidos o OpenAPI (Swagger).
\n\nEjemplo: backend con Express y TypeScript
\n\nimport express, { Request, Response } from 'express';\n\ninterface User {\n id: number;\n name: string;\n email: string;\n}\n\nconst app = express();\napp.get('/api/users/:id', (req: Request, res: Response) => {\n const user: User = { id: +req.params.id, name: 'Alice', email: 'alice@example.com' };\n res.json(user);\n});\n\n\nFrontend (fetch):
\n\ninterface User {\n id: number;\n name: string;\n email: string;\n}\n\nasync function getUser(id: number): Promise<User> {\n const res = await fetch(`/api/users/${id}`);\n return res.json() as Promise<User>;\n}\n\n\nProblema: si el backend cambia la estructura de User, el frontend se entera solo en tiempo de ejecución. Los tipos en el frontend son solo una copia. Solución: generar tipos a partir de la especificación OpenAPI.
\n\nVentajas de REST en TypeScript
\n- \n
- Simplicidad de caché: El caché HTTP (CDN, navegador) funciona de serie. \n
- Estructura clara: URL = recurso, métodos = acciones (GET, POST, PUT, DELETE). \n
- Amplio soporte: Cualquier cliente (navegador, curl, Postman) entiende REST. \n
- Baja barrera de entrada: Incluso un junior lo entenderá en una hora. \n
Desventajas de REST
\n- \n
- Over-fetching y Under-fetching: O arrastras campos innecesarios o haces varias solicitudes. \n
- Estructura rígida: Para obtener un usuario + sus publicaciones, necesitas dos solicitudes o parches (campo expand). \n
- Tipado débil: Sin OpenAPI, los tipos en el cliente son solo "palabra de honor". \n
GraphQL: flexibilidad y control
\n\nGraphQL es un lenguaje de consultas que le da al cliente el derecho de decidir qué datos recibir. Un solo endpoint (/graphql), una sola consulta, y obtienes exactamente lo que pediste. TypeScript y GraphQL son la pareja ideal: los tipos se generan automáticamente a partir del esquema.
Tipado en GraphQL con TypeScript
\nPrimero se escribe el esquema (SDL):
\n\ntype User {\n id: ID!\n name: String!\n email: String!\n posts: [Post!]!\n}\n\ntype Post {\n id: ID!\n title: String!\n content: String!\n}\n\ntype Query {\n user(id: ID!): User\n}\n\n\nLuego se generan los tipos (mediante graphql-codegen):
// generated.ts\nexport type User = {\n __typename?: 'User';\n id: string;\n name: string;\n email: string;\n posts: Array<Post>;\n};\n\nexport type Post = {\n __typename?: 'Post';\n id: string;\n title: string;\n content: string;\n};\n