GraphQL TypeScript 库:现代化的 API 方法
GraphQL 是一种 API 查询语言,允许客户端仅请求所需的数据。与 TypeScript 结合使用时,它提供了强大的类型系统,确保了安全性和自动补全功能。在 pythonlib.ru 上,我们将解析在 TypeScript 中用于 GraphQL 的关键库——type-graphql,以及其替代方案。
为什么选择 TypeScript + GraphQL?
TypeScript 添加了静态类型检查,这对于大型项目至关重要。通过 TypeScript 类描述的 GraphQL 模式成为唯一的真实来源:代码中的更改会自动与 API 同步。这消除了文档与服务器实际行为之间的差异。
主要库:TypeGraphQL
type-graphql 是一个使用装饰器在 TypeScript 中创建 GraphQL API 的框架。它遵循 code-first 原则:您通过代码定义模式,而不是通过 SDL(模式定义语言)。
安装
npm install type-graphql graphql reflect-metadata在 tsconfig.json 中添加:
{ "emitDecoratorMetadata": true, "experimentalDecorators": true}示例:定义类型和解析器
让我们创建一个简单的用户模型和用于获取数据的解析器。
import { ObjectType, Field, ID, Resolver, Query } from "type-graphql";
@ObjectType()class User { @Field(() => ID) id: number;
@Field() name: string;
@Field({ nullable: true }) email?: string;}
@Resolver()class UserResolver { @Query(() => [User]) users(): User[] { return [ { id: 1, name: "安娜", email: "anna@example.com" }, { id: 2, name: "鲍里斯", email: null } ]; }}构建并启动服务器
import { buildSchema } from "type-graphql";import { ApolloServer } from "@apollo/server";import { startStandaloneServer } from "@apollo/server/standalone";
async function main() { const schema = await buildSchema({ resolvers: [UserResolver] });
const server = new ApolloServer({ schema }); const { url } = await startStandaloneServer(server, { listen: { port: 4000 } }); console.log(`服务器已启动:${url}`);}
main();替代库
- NestJS + GraphQL — 与流行框架的集成。使用基于
type-graphql的@nestjs/graphql。 - GraphQL Nexus — 无装饰器的 code-first 库,使用方法链。
- Pothos GraphQL — 现代化的 code-first 库,对 TypeScript 有出色的支持。
TypeGraphQL 的高级功能
参数和变更
import { Arg, Mutation } from "type-graphql";
@Resolver()class UserResolver { @Mutation(() => User) createUser(@Arg("name") name: string, @Arg("email") email: string): User { return { id: 3, name, email }; }}使用 class-validator 进行验证
import { Length, IsEmail } from "class-validator";import { InputType, Field } from "type-graphql";
@InputType()class CreateUserInput { @Field() @Length(2, 30) name: string;
@Field() @IsEmail() email: string;}通过中间件进行授权
import { UseMiddleware } from "type-graphql";
function AuthMiddleware(): MiddlewareFn { return async ({ context }, next) => { if (!context.user) throw new Error("未授权"); return next(); };}
@Resolver()class UserResolver { @Query(() => User) @UseMiddleware(AuthMiddleware) me(): User { return { id: 1, name: "当前用户", email: "user@example.com" }; }}