Introduction to GraphQL and TypeScript
GraphQL is a query language for APIs that allows clients to request only the data they actually need. Combined with TypeScript, which adds static typing to JavaScript, you get a powerful tool for creating reliable and scalable APIs. In this tutorial, we will create a simple GraphQL API in TypeScript step by step. You will learn how to set up a project, define a schema, write resolvers, and execute queries.
This material is aimed at beginner developers who are familiar with the basics of JavaScript and want to master modern technologies. By the end of the article, you will be able to deploy a basic GraphQL server on your own.
Step 1: Project Setup
Before writing code, you need to initialize the project and install dependencies. We will use Apollo Server — one of the most popular libraries for working with GraphQL in Node.js.
npm Initialization
Create a new directory and run the initialization:
mkdir graphql-typescript-tutorialcd graphql-typescript-tutorialnpm init -yInstalling Dependencies
Install the necessary packages:
npm install apollo-server graphqlnpm install typescript ts-node @types/node --save-devapollo-server— server for handling GraphQL queries.graphql— core of the GraphQL language.typescriptandts-node— for compiling and running TypeScript.
TypeScript Configuration
Create a tsconfig.json file in the project root:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "esModuleInterop": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"], "exclude": ["node_modules"]}Create a src folder and an index.ts file — this will contain the main server code.
Step 2: Defining the Schema and Types
The GraphQL schema describes what data is available and how it can be queried. In TypeScript, we will use a string with gql syntax to define types.
Basic Schema
Open src/index.ts and add the following code:
import { ApolloServer, gql } from 'apollo-server';
const typeDefs = gql` type Book { id: ID! title: String! author: String! }
type Query { books: [Book] book(id: ID!): Book }`;Here we defined a Book type with fields id, title, and author. The Query contains two queries: fetching all books and fetching a single book by ID.
Mock Data
For testing, let's add an array of books:
const books = [ { id: '1', title: 'War and Peace', author: 'Leo Tolstoy' }, { id: '2', title: 'Crime and Punishment', author: 'Fyodor Dostoevsky' },];Step 3: Writing Resolvers
Resolvers are functions that return data for each field of the schema. They connect the schema to the actual data.
Implementing Resolvers
Add the resolvers object:
const resolvers = { Query: { books: () => books, book: (_: any, args: { id: string }) => { return books.find(book => book.id === args.id); }, },};The first argument _ is the parent object (not used in this case). The second argument args contains query parameters, for example, id.
Building the Server
Now let's create a server instance and start it:
const server = new ApolloServer({ typeDefs, resolvers });
server.listen().then(({ url }) => { console.log(`🚀 Server running at ${url}`);});