使用TypeScript构建GraphQL API:逐步实践教程

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言

\n\n

GraphQL是一种用于API的查询语言,它允许客户端仅获取所需的数据。与TypeScript结合使用时,它成为创建类型安全、可扩展且文档完善的API的强大工具。在本逐步教程中,我们将使用Apollo Server和TypeGraphQL实际构建一个完整的基于TypeScript的GraphQL API。

\n\n

您将了解到:

\n
    \n
  • 如何配置一个包含TypeScript和Apollo Server的项目
  • \n
  • 如何使用TypeGraphQL装饰器定义GraphQL模式
  • \n
  • 如何编写具有完整类型定义的解析器
  • \n
  • 如何连接数据库并执行查询
  • \n
\n\n

本材料对初学者以及已熟悉REST API但希望掌握构建API的现代方法的开发者都很有帮助。

\n\n

1. 项目配置与依赖安装

\n\n

我们从初始化项目开始。请确保您已安装Node.js(版本16+)和npm/yarn。

\n\n
mkdir graphql-ts-tutorial\ncd graphql-ts-tutorial\nnpm init -y
\n\n

安装必要的包:

\n\n
npm install apollo-server graphql reflect-metadata type-graphql class-validator\nnpm install -D typescript @types/node ts-node
\n\n

创建tsconfig.json文件:

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

请注意experimentalDecorators和emitDecoratorMetadata标志——它们是TypeGraphQL工作所必需的。

\n\n

2. 使用TypeGraphQL定义模式和类型

\n\n

创建src文件夹和文件src/types/User.ts。在这里我们将描述用户模型。

\n\n
import { ObjectType, Field, ID, InputType } from "type-graphql";\n\n@ObjectType()\nexport class User {\n  @Field(() => ID)\n  id!: number;\n\n  @Field()\n  name!: string;\n\n  @Field()\n  email!: string;\n\n  @Field()\n  createdAt!: Date;\n}
\n\n

说明:

\n
    \n
  • @ObjectType() — 将类标记为GraphQL类型。
  • \n
  • @Field() — 指示哪些字段将在API中可用。
  • \n
  • @Field(() => ID) — 用于标量类型ID。
  • \n
\n\n

现在为变更(创建用户)创建一个InputType:

\n\n
@InputType()\nexport class CreateUserInput {\n  @Field()\n  name!: string;\n\n  @Field()\n  email!: string;\n}
\n\n

此类型将用于解析器中进行输入数据验证。

\n\n

3. 编写解析器

\n\n

创建文件src/resolvers/UserResolver.ts。在这里我们将实现查询和变更的逻辑。

\n\n
import { Resolver, Query, Mutation, Arg } from "type-graphql";\nimport { User, CreateUserInput } from "../types/User";\n\n// 模拟数据库\nlet users: User[] = [\n  { id: 1, name: "伊万·伊万诺夫", email: "ivan@example.com", createdAt: new Date() },\n  { id: 2, name: "玛丽亚·彼得罗娃", email: "maria@example.com", createdAt: new Date() }\n];\n\nlet nextId = 3;\n\n@Resolver()\nexport class UserResolver {\n  @Query(() => [User])\n  async users(): Promise<User[]> {\n    return users;\n  }\n\n  @Query(() => User, { nullable: true })\n  async user(@Arg("id") id: number): Promise<User | undefined> {\n    return users.find(u => u.id === id);\n  }\n\n  @Mutation(() => User)\n  async createUser(@Arg("data") data: CreateUserInput): Promise<User> {\n    const newUser: User = {\n      id: nextId++,\n      name: data.name,\n      email: data.email,\n      createdAt: new Date()\n    };\n    users.push(ne                

博客

书籍推荐