GraphQL is a powerful query language designed to build flexible apis. It allows you to define a type system for data, so that when a query is executed, it returns only the data you need.
GraphQL provides a better experience for developers when used with TypeScript because they are both type languages. TypeScript is a typed superset of JavaScript that can be extended by adding types. Therefore, using these techniques together will certainly help you build predictable and strongly typed apis.
In this tutorial, I’ll first explain why you combine these technologies, and then show you how to use TypeScript with GraphQL by building an API from scratch using TypeGraphQL.
A prerequisite for
This tutorial assumes experience with TypeScript, especially with TypeScript classes and decorators. Knowledge of GraphQL will come in handy, but it’s not mandatory.
In this tutorial, we’ll use TypeGraphQL, a modern framework for building GraphQL APIS using Node.js and TypeScript.
Why use TypeScript with GraphQL
TypeScript is a popular programming language developed and maintained by Microsoft. It’s a superset of JavaScript that uses static type checking to make code predictable.
Over the years, TypeScript has proven to be a valuable language for large code bases. TypeScript uses its types to improve code quality, which in turn makes code more robust, understandable, and predictable.
GraphQL solves the problem of over-fetching or under-fetching apis. GraphQL gets all the data you need for your application in a single request. In this way, GraphQL makes your queries flexible, and your API readable and easy to learn.
TypeScript and GraphQL both rely on types to make code easy to understand. However, the GraphQL type can only be defined in the GraphQL schema using the buildSchema method or a file with the.gQL extension. The GraphQL parser does not support the GraphQL type because the parser is just a regular JavaScript function, not GraphQL code. TypeScript solves this problem because, as we mentioned earlier, it is a superset of JavaScript. Therefore, it can set the type on the GraphQL parser. That’s why it makes sense to use TypeScript with GraphQL.
GraphQL handles GraphQL schema types, while TypeScript sets types on the GraphQL parser. However, building strongly typed apis using Node.js, GraphQL, and TypeScript can be difficult to maintain because you’re dealing with multiple languages.
TypeGraphQL is intended to address the problem of maintaining consistency between schema and parser. TypeGraphQL allows you to use TypeScript classes and decorators to create schemas, types, and parsers for apis. It uses TypeScript to build the entire GraphQL API.
So far, we’ve seen why TypeScript works with GraphQL and why TypeGraphQL is handy for building and maintaining GraphQL apis using TypeScript versions.
Without further ado, let’s dive into the exercise section and build the GraphQL API using TypeGraphQL.
The installation
Before using TypeScript and GraphQL, we need to create a Node.js application, open your terminal interface, and execute the following command:
yarn init
Copy the code
Or use the NPM package manager
npm init
Copy the code
Then you need to set up some information for the project, which you don’t need to enter, and finally generate a package.json file in the project directory.
Fantingshengdemacbook-pro: GraphqL-typescript FantingSheng $YARN Init Yarn Init v1.12.3 question name Graphql-typescript: Question Version (1.0.0): question description: for study question entry point (index.js): question repository url: https://github.com/fantingsheng/graphql-typescript question author: Timfan Question License (MIT): Question private: Success Saved package.json ✨ Done in 223.35s.Copy the code
Next, install some of the required dependencies
yarn add express apollo-server-express graphql reflect-metadata type-graphql class-validator
Copy the code
or
npm install express apollo-server-express graphql reflect-metadata type-graphql class-validator
Copy the code
Let’s download these packages and then explain what they do. Also install their type definitions to support the use of TypeScript.
yarn add -D ts-node typescript @types/express @types/node nodemon
Copy the code
or
npm install -D ts-node typescript @types/express @types/node nodemon
Copy the code
Note: We installed Nodemon to hot-reload when the code is updated
Here is an explanation of what each dependency library does:
express
Is a minimalist Web framework for Nodeapollo-server-express
Is one that allows us to use in the Apollo GraphQL serviceexpress
The middlewarereflect-metadata
Enables TypeScript decorators to add classes and members to a class when it is already defined. It is a dependency on TypeGraphQL.class-validator
allowTypeGraphQL
Use decorators and non-decorators in validation-based cases
Next, build the structure for the project
The SRC | ├ ─ ─ resolvers | | └ ─ ─ todoResolver. Ts | └ ─ ─ schemas | | └ ─ ─ Todo. Ts | └ ─ ─ but ts ├ ─ ─ tsconfig. Json ├ ─ ─ Package. The json └ ─ ─ yarn. The lockCopy the code
Here are four files that need to be explained:
- The entry file for the application
index.ts
schemas
The directory contains the GraphQL Schema for the projectresolvers
The directory contains all API implementationstsconfig.json
Tell TypeScript how to compile code
In the meantime, we need to add the service’s execution command to the package.json file:
"scripts": {
"start": "nodemon --exec ts-node src/index.ts"
}
Copy the code
The script command is used to start the service by using nodemon. Even if the code is temporarily modified, it will restart and take effect.
Add configuration to the tsconfig.json file
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true
}
}
Copy the code
Both properties need to be set to true so that we can use TypeScript decorators in our projects.
We are now ready to create a GraphQL Schema for the API.
Create GraphQL Schema
TypeGraphQL allows you to create a schema with TypeScript classes and decorators, which are just syntactic sugar that ultimately generates GraphQL code. We’ll talk about that later, but let’s create a schema
schema/Todo.ts
import { Field, ObjectType, InputType } from "type-graphql"
@ObjectType() export class Todo {
@Field() id: number
@Field() title: string
@Field() description: string
@Field() status: boolean
}
@InputType() export class TodoInput implements Partial<Todo> {
@Field() title: string
@Field() description: string
}
Copy the code
This syntax may seem odd at first glance, but it’s nothing more than the addition of TypeScript decorators and classes. Right
Here @objectType () is provided by TypeGraphQL and exists to create new objects and schemas. The Todo class reflects the structure of the Todo object, and TodoInput defines the expected data structure we add to Todo.
Here is the GraphQL code for the same function.
type Todo {
id: ID!
title: String!
description: String!
status: Boolean!
}
input TodoInput {
title: String!
description: String!
}
Copy the code
You can see that the logic is exactly the same, except that TypeScript is not used.
Create GraphQL Resolver
Unlike GraphQL, TypeGraphQL writes query and mutation statements inside the resolver, using the method name as the only entry when called.
import { Query, Resolver, Mutation, Arg } from "type-graphql";
import { Todo, TodoInput } from "../schemas/Todo";
@Resolver(of => Todo)
export class TodoResolver {
private todos: Todo[] = []
@Query(returns => [Todo], { nullable: true })
async getTodos(): Promise<Todo[]> {
return await this.todos;
}
@Mutation(returns => Todo)
async addTodo(@Arg('todoInput') {title, description }: TodoInput): Promise<Todo> {
const todo = {
id: Math.random(),
title,
description,
status: false
}
await this.todos.push(todo)
return todo;
}
}
Copy the code
Here we use the Resolver decorator to create a new GraphQL resolver that returns Todo. Then, create a GraphQL Query to query all of the Todo data.
After that, we define a mutation Query to add a new set of data to the Todo array.
Let’s put the code into GraphQL form
type Mutation { addTodo(todoInput: TodoInput!) : Todo! } type Query { getTodos: [Todo!] }Copy the code
At this point, we are ready to build the service by creating a schema and resolver.
Set up service
src/index.ts
import "reflect-metadata";
import { ApolloServer } from "apollo-server-express";
import * as Express from "express";
import { buildSchema } from "type-graphql";
import { TodoResolver } from "./resolvers/todoResolver";
async function main() {
const schema = await buildSchema({
resolvers: [TodoResolver],
emitSchemaFile: true
});
const app = Express();
const server = new ApolloServer({
schema
});
server.applyMiddleware({ app });
app.listen(4000, () =>
console.log("Server is running on http://localhost:4000/graphql")
);
}
main();
Copy the code
We import TodoResolver and create a new GraphQL Schema by passing in the resolver argument in the buildSchema method.
Then create a ApolloServer from the Schema object
Set the property emitSchemaFile: true to allow TypeGraphQL to generate a schema.gQL file during the packaging phase.
Run the following command to start the application
yarn start
Copy the code
or
npm start
Copy the code
Access it in a browserhttp://localhost:4000/graphql
A schema. GQL file is generated in the project root directory
# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- #!!!!!! THIS FILE WAS GENERATED BY TYPE-GRAPHQL !!! #!!!!!! DO NOT MODIFY THIS FILE BY YOURSELF !!! # ----------------------------------------------- type Mutation { addTodo(todoInput: TodoInput!) : Todo! } type Query { getTodos: [Todo!] } type Todo { description: String! id: Float! status: Boolean! title: String! } input TodoInput { description: String! title: String! }Copy the code
Then add the following code to the GraphQL runner to create a new Todo
mutation {
addTodo(todoInput: { title: "Todo 1", description: "This is my todo" }) {
title
description
status
}
}
Copy the code
Then use the following GraphQL Query to query the new Todo
{
getTodos {
title
description
status
}
}
Copy the code
Ok, so we’re done.
We’ve implemented building the GraphQL API using TypeScript.
The complete code
Github.com/fantingshen…
Reference:
- TypeGraphQL Docs
- TypeScript Decorators Docs
- TypeScript Classes Docs
- TypeGraphQL Examples
- GraphQL Docs
For more articles by the author, focus on space programming of the public