如何在 GraphQL 中使用 TypeScript
GraphQL 是一种强大的查询语言,可用于构建灵活的 API。它允许您为数据定义类型系统,因此在执行查询时,它只会返回您需要的数据。
GraphQL 与 TypeScript 结合使用可以提供更佳的开发者体验,因为它们都是类型语言。TypeScript 是 JavaScript 的类型化超集,它通过添加类型扩展了 JavaScript。因此,结合使用这两种技术无疑有助于构建可预测且强类型的 API。
在本教程中,我将首先解释为什么要结合这些技术,然后向您展示如何使用 TypeGraphQL 从头开始构建 API,从而将 TypeScript 与 GraphQL 结合使用。
先决条件
本教程假设您已具备一定的 TypeScript 使用经验,特别是 TypeScript 类和装饰器方面的经验。了解 GraphQL 会有所帮助,但并非必需。
在本指南中,我们将使用TypeGraphQL,这是一个使用 Node.js 和 TypeScript 构建 GraphQL API 的现代框架。
为什么要将 TypeScript 与 GraphQL 结合使用
TypeScript 是一种由微软开发和维护的流行编程语言。它是 JavaScript 的超集,使用静态类型检查来保证代码的可预测性。
多年来,TypeScript 已被证明是大型代码库的理想语言。TypeScript 通过其类型系统提升代码质量,从而带来诸多优势,例如代码的健壮性、可理解性和可预测性。
GraphQL 解决了 API 数据获取过多或过少的问题。它为所有请求提供了一个统一的端点,通过一个Post方法精确获取所需数据,不多不少。这样,GraphQL 使查询更加灵活,API 也更易读易学。
TypeScript 和 GraphQL 都依赖类型来使代码更易于理解。然而,GraphQL 类型只能在 GraphQL schema 中使用 `type` 方法buildSchema或带有 `.py` 扩展名的文件来定义.gql。GraphQL 类型在 GraphQL 解析器中不受支持,因为解析器只是普通的 JavaScript 函数,而不是 GraphQL 代码。TypeScript 解决了这个问题,因为正如我们前面提到的,它是 JavaScript 的超集。因此,它可以为 GraphQL 解析器设置类型。这就是为什么将 TypeScript 与 GraphQL 结合使用是合理的。
GraphQL 负责处理 GraphQL schema 的类型,而 TypeScript 则负责设置 GraphQL 解析器的类型。然而,由于需要处理多种语言,使用 Node.js、GraphQL 和 TypeScript 构建强类型 API 的维护可能会面临挑战。
TypeGraphQL 旨在解决模式和解析器之间的一致性问题。它允许你使用 TypeScript 类和装饰器来创建 API 的模式、类型和解析器。它使用 TypeScript 构建整个 GraphQL API。
插图
到目前为止,我们已经了解了为什么将 TypeScript 与 GraphQL 结合使用会很有用,以及为什么 TypeGraphQL 对于构建和维护使用 TypeScript 的 GraphQL API 非常方便。
事不宜迟,让我们直接进入实践部分,使用 TypeGraphQL 构建 GraphQL API。
设置
要使用 TypeScript 和 GraphQL,我们首先需要创建一个新的 Node.js 应用程序。
打开命令行界面 (CLI) 并运行以下命令:
yarn init
或者为了npm
npm init
您需要回答几个配置问题,系统会生成一个package.json文件。接下来,安装本教程所需的依赖项。
yarn add express apollo-server-express graphql reflect-metadata type-graphql class-validator
为了npm
npm install express apollo-server-express graphql reflect-metadata type-graphql class-validator
稍后我们会详细介绍这些包及其功能。现在,让我们先安装它们的类型,以便 TypeScript 能够识别这些库。
yarn add -D @types/express @types/node nodemon
或者
npm install -D @types/express @types/node nodemon
请注意,我们nodemon还安装了实时重新加载功能,以便在发生更改时自动更新。
以下是每个已安装库的功能:
express是一个极简的 Node.js Web 框架apollo-server-express是一个允许express在 Apollo GraphQL 服务器中使用的中间件。reflect-metadata它允许 TypeScript 装饰器在定义类时增强类及其成员的功能。它是 TypeGraphQL 的一个依赖项。class-validator允许 TypeGraphQL 使用基于装饰器和非装饰器的验证。
接下来,我们需要按如下方式构建项目:
src
| ├── resolvers
| | └── todoResolver.ts
| └── schemas
| | └── Todo.ts
| └── index.ts
├── tsconfig.json
├── package.json
└── yarn.lock
这里,有四个文件需要重点标注:
- 服务器的入口点(
index.ts)。 schemas包含项目 GraphQL Schema 的文件夹。resolvers存放 API 解析器的文件夹。- 该
tsconfig.json文件告诉 TypeScript 如何编译代码。
完成这些步骤后,我们现在可以在package.json文件中添加启动服务器的脚本。
"scripts": {
"start": "nodemon --exec ts-node src/index.ts"
}
此脚本将启动服务器nodemon。每当我们的代码更新时,它都会重新启动。
现在让我们来配置一下tsconfig.json。
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true
}
}
这两个属性应该设置为 true,true才能在项目中使用 TypeScript 装饰器。
现在我们可以为 API 构建 GraphQL Schema 了。
构建 GraphQL Schema
TypeGraphQL 允许你使用 TypeScript 类和装饰器构建模式。它只是语法糖,因为 TypeGraphQL 底层仍然会生成常规的 GraphQL 代码。我们稍后会看到生成的代码——现在,让我们先创建模式。
schemas/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 {
@Field() title: string
@Field() description: string
}
乍一看语法可能有点奇怪,但其实很容易理解。它只是TypeScript的装饰器和类而已。
这里,@ObjectType()TypeGraphQL 提供的功能允许创建新的对象或模式。该类Todo反映了 Todo 对象的结构,并TodoInput定义了添加新 Todo 所需的数据。
现在,让我们用 GraphQL 编写相同的代码。
type Todo {
id: ID!
title: String!
description: String!
status: Boolean!
}
input TodoInput {
title: String!
description: String!
}
如你所见,逻辑是一样的。唯一的区别在于,这里我们没有使用 TypeScript。
现在我们准备创建 GraphQL 解析器了。
创建 GraphQL 解析器
与 GraphQL 不同,TypeGraphQL 将 GraphQL 查询或变更操作放在解析器中。函数名称将用作查询或修改数据的端点。
resolvers/todoResolver.ts
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(), // not really unique
title,
description,
status: false,
}
await this.todos.push(todo)
return todo
}
}
这里,我们使用Resolver装饰器创建一个新的 GraphQL 解析器,该解析器返回一个 Todo 对象。接下来,我们构建一个 GraphQL 查询来获取所有 Todo 对象。
之后,我们定义一个变更查询,该查询需要一个参数title和一个值,description以便在数据数组中添加一个新的待办事项。
顺便说一下,这里不需要使用 async/await,因为这段代码不会花费太多时间完成。但我还是把它写在这里,以备你在实际处理服务器时参考。
现在让我们把代码转换成 GraphQL。
type Mutation {
addTodo(todoInput: TodoInput!): Todo!
}
type Query {
getTodos: [Todo!]
}
有了这些,我们就可以构建使用我们刚刚创建的模式和解析器的服务器了。
创建服务器
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()
如您所见,我们导入了 `Todo` 库TodoResolver,它需要作为解析器传递给该buildSchema方法。这样,TypeGraphQL 就可以基于 `Todo` 解析器构建一个新的 GraphQL Schema。
接下来,我们将该schema对象(其中包含 GraphQL schema 和解析器)传递给 Apollo 以创建服务器。
设置该属性emitSchemaFile: true允许 TypeGraphQLschema.gql在构建时生成文件。
我们来检查一下应用是否正常运行。运行以下命令:
yarn start
或者
npm start
访问http://localhost:4000/graphql,然后将下面的代码块添加到 GraphQL Playground 中以创建一个新的待办事项。
mutation {
addTodo(todoInput: { title: "Todo 1", description: "This is my todo" }) {
title
description
status
}
}
Todo 对象应该已成功创建!
待办事项已创建
现在使用以下 GraphQL 查询来查询新创建的待办事项。
{
getTodos {
title
description
status
}
}
你应该看到所有待办事项都已返回。
所有待办事项
太棒了!我们的应用看起来不错。
我们现在已经完成了使用 TypeScript 构建 GraphQL API 的工作。
你可以在这个GitHub 仓库中找到最终项目。
感谢阅读
TakeShape 中的 GraphQL
TakeShape 提供灵活的 GraphQL API,让您轻松管理内容。通过 API Explorer,您可以立即查看内容模型更改对 API 的影响。您无需自行构建任何后端,一切都已为您设置完毕。TakeShape 会自动生成安全的 GraphQL API,用于公开您的所有内容和服务。
下一步
请查看以下资源,深入了解本教程的内容:
文章来源:https://dev.to/takeshape/how-to-use-typescript-with-graphql-3k98
