GraphQL API with TypeScript: Step-by-Step Tutorial

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
```html

GraphQL API with TypeScript: Step-by-Step Tutorial

GraphQL is a query language for APIs that allows clients to request only the data they need. Combined with TypeScript, static typing helps avoid errors at the development stage and makes the code more predictable. In this tutorial, we will create a full-fledged GraphQL API using Apollo Server and TypeScript.

We will cover: project setup, schema and type definition, resolver implementation, mutations for data modification, and database integration (in-memory for simplicity). By the end of the article, you will be able to run your own GraphQL server.

1. Project Preparation and Dependency Installation

First, let's create a new Node.js project and install the necessary packages.

mkdir graphql-typescript-tutorial
cd graphql-typescript-tutorial
npm init -y
npm install apollo-server graphql
npm install -D typescript @types/node ts-node nodemon

Let's create the tsconfig.json file:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "rootDir": "./src",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}

The project structure will be as follows:

  • src/index.ts — entry point
  • src/schema.ts — GraphQL schema
  • src/resolvers.ts — resolvers
  • src/types.ts — TypeScript types

2. Defining GraphQL Types and Schema

The GraphQL schema describes what data is available and how to request it. For this example, we'll create a simple user and post management system.

Let's create 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;
}

Now let's create src/schema.ts with the GraphQL type definitions:

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!
  }
`;

Note: we use input types for mutations — this is a standard practice in GraphQL.

3. Implementing Resolvers with TypeScript

Resolvers are functions that return data for each field of the schema. Let's create src/resolvers.ts:

import { User, Post, CreateUserInput, CreatePostInput } from './types';

// In-memory database
let 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,
```                

Blogs

Book Recommendations