GraphQL API with TypeScript: Step-by-Step Tutorial for Developers

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction to GraphQL API with TypeScript



GraphQL is a modern query language for APIs that allows clients to request only the data they actually need. Combined with TypeScript, which adds strict typing, development becomes more predictable and safer. In this step-by-step tutorial, we will create a full-fledged GraphQL API in TypeScript using popular tools and best practices.



Why choose GraphQL with TypeScript? First, you get autocompletion and type checking at compile time. Second, GraphQL allows combining multiple queries into one, reducing the number of network requests. Third, TypeScript is ideal for describing complex graph data structures.



Project setup and dependency installation



To start, let's create a new project and install the necessary packages. We will use Apollo Server — the most popular server for GraphQL, and TypeGraphQL for convenient integration with 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 --init


After installation, configure tsconfig.json. Make sure the following options are enabled:



{  "compilerOptions": {    "target": "ES2020",    "module": "commonjs",    "lib": ["ES2020"],    "experimentalDecorators": true,    "emitDecoratorMetadata": true,    "outDir": "./dist",    "rootDir": "./src",    "strict": true,    "esModuleInterop": true  }}


Create the folder structure:



src/  ├── index.ts  ├── resolvers/  │   └── user.resolver.ts  ├── schemas/  │   └── user.schema.ts  └── data/      └── users.ts


Creating the schema and data types



In TypeGraphQL, data types are described using decorators. Let's create a user model and an input type for mutations.



// 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;}


Note the use of @ObjectType() to describe return types and @InputType() for input parameters. This allows TypeGraphQL to automatically generate the GraphQL schema.



Implementing resolvers



Resolvers are functions that process queries and return data. Let's create a simple in-memory array to store users.



// src/data/users.tsimport { User } from "../schemas/user.schema";

export const users: User[] = [ { id: 1, name: "Ivan Petrov", email: "ivan@example.com", age: 28 }, { id: 2, name: "Maria Sidorova", email: "maria@example.com", age: 32 },];


Now let's write resolvers for queries and mutations:



// 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 =

Blogs

Book Recommendations