新闻详情

新闻详情

首页 / 资讯中心 / 详情

TypeGraphQL 入门指南:用 TypeScript 类与装饰器构建一个食谱 GraphQL API

发布时间:2026/9/27 21:40:55来源:尧图网络
TypeGraphQL 入门指南:用 TypeScript 类与装饰器构建一个食谱 GraphQL API
后端GraphQLAPI设计【免费下载链接】type-graphqlCreate GraphQL schema and resolvers with TypeScript, using classes and decorators!项目地址https://gitcode.com/gh_mirrors/ty/type-graphql点击查看免费下载TypeGraphQL 的核心思路是用 TypeScript 的类class和装饰器decorator声明式地定义 GraphQL 类型、查询Query、变更Mutation与输入参数从而让 Schema 定义与业务代码完全同构。本文以官方入门文档website/versioned_docs/version-0.17.1/getting-started.md与 docs/getting-started.md 内容一致为主线从零构建一个烹饪食谱示例 API完整覆盖ObjectType、Field、Resolver、Query、Mutation、Arg、InputType、ArgsType以及buildSchema的完整链路并结合仓库源码src/、examples/simple-usage/讲解底层原理。读完本文你将掌握用 TypeGraphQL 写出一个可运行、可校验、带权限控制的完整 GraphQL 服务的全部基本步骤。前置准备环境与 TypeScript 配置本文假设你已经完成了 安装指南 中的全部步骤。安装 TypeGraphQL 需要三样东西主包type-graphql、其 peer 依赖graphqlGraphQL 官方 JS 实现及类型定义以及让装饰器类型反射生效的reflect-metadatashimnpm i graphql types/graphql type-graphql npm i reflect-metadatareflect-metadata必须在入口文件的最顶部导入早于任何type-graphql或 resolver 的 import否则装饰器拿不到design:type等元数据import reflect-metadata;tsconfig.json中必须开启两个关键选项并配合 ES2016 目标{ compilerOptions: { target: es2016, module: commonjs, lib: [es2016, esnext.asynciterable], experimentalDecorators: true, emitDecoratorMetadata: true } }其中experimentalDecorators启用装饰器语法emitDecoratorMetadata让 TypeScript 在编译期把属性/返回值的类型信息写入元数据——这是 TypeGraphQL 在未显式给出类型函数时推断类型的根基。esnext.asynciterable是订阅功能依赖AsyncIterator时所需的 lib 项。Types用ObjectType与Field定义 Recipe 类型我们的目标是得到如下 SDL 描述的Recipe类型type Recipe { id: ID! title: String! description: String creationDate: Date! ingredients: [String!]! }先写一个没有任何装饰器的普通 TypeScript 类把属性和类型声明清楚class Recipe { id: string; title: string; description?: string; creationDate: Date; ingredients: string[]; }然后为类和每个属性加上装饰器TypeGraphQL 会据此生成对应的 GraphQL 类型ObjectType() class Recipe { Field(type ID) id: string; Field() title: string; Field({ nullable: true }) description?: string; Field() creationDate: Date; Field(type [String]) ingredients: string[]; }关键点拆解ObjectType()标记一个类为 GraphQL Object Type。从源码看ObjectType.ts 支持无参、传选项对象或传自定义名称name三种重载还支持description、implements接口实现等选项。Field()将类属性暴露为 GraphQL 字段。默认情况下类型由 TypeScript 反射design:type推断string→String、number→Float、boolean→Boolean、Date→ 内置的Date标量。type ID和type [String]是返回类型函数用于指定ID标量与数组类型。type [String]生成的是[String!]!——元素非空、数组本身也非空这正是文档目标 SDL 中ingredients: [String!]!的来源。{ nullable: true }控制可空性description?: string配合nullable: true生成description: String。nullable、array等的完整规则详见 fields and types docs。在仓库中examples/simple-usage/recipe.type.ts 给出了一个更丰富的实践版本它同时演示了description、deprecationReason字段废弃提示、基于 getter 的计算字段averageRating以及Float/Int标量映射。Resolvers用Resolver组织查询与变更类型定义好后创建 resolver可类比控制器/controller类。它通过构造函数注入RecipeService并提供典型的 CRUD 查询与变更Resolver(Recipe) class RecipeResolver { constructor(private recipeService: RecipeService) {} Query(returns Recipe) async recipe(Arg(id) id: string) { const recipe await this.recipeService.findById(id); if (recipe undefined) { throw new RecipeNotFoundError(id); } return recipe; } Query(returns [Recipe]) recipes(Args() { skip, take }: RecipesArgs) { return this.recipeService.findAll({ skip, take }); } Mutation(returns Recipe) Authorized() addRecipe( Arg(newRecipeData) newRecipeData: NewRecipeInput, Ctx(user) user: User, ): PromiseRecipe { return this.recipeService.addNew({ data: newRecipeData, user }); } Mutation(returns Boolean) Authorized(Roles.Admin) async removeRecipe(Arg(id) id: string) { try { await this.recipeService.removeById(id); return true; } catch { return false; } } }逐项说明Resolver(Recipe)声明该 resolver 服务于Recipe类型。源码 Resolver.ts 支持无参、传类、传返回类型函数三种形式若不传任何类型在构建 schema 时会抛出 No provided object type 错误。Query(returns Recipe)定义 GraphQL 查询。returns ...返回类型函数在这里是必需的因为方法的返回类型无法通过反射可靠推断如PromiseRecipe。源码 Query.ts 会把方法元数据收集进Queryhandler 列表。Arg(id)声明单个查询参数Args()则将一组参数合并为一个对象见下文RecipesArgs。Ctx(user)从上下文context中取出user对象用于获取当前请求的用户身份。Authorized()与Authorized(Roles.Admin)是权限装饰器无参表示仅限已认证用户带角色参数则进一步要求满足角色条件。从源码 Authorized.ts 看它可以作用在 resolver 类、方法或字段上并把roles收集为授权元数据最终由用户提供的 auth checker 消费详见 authorization 文档。returns Recipe为何必须写成函数、何时省略等细节见 resolvers docs。Inputs 与 ArgumentsInputType、ArgsType与自动校验NewRecipeInput和RecipesArgs同样是普通的类只不过分别用InputType()与ArgsType()标记并叠加class-validator的校验装饰器InputType() class NewRecipeDataInput { Field() MaxLength(30) title: string; Field({ nullable: true }) Length(30, 255) description?: string; Field(type [String]) ArrayMaxSize(30) ingredients: string[]; } ArgsType() class RecipesArgs { Field(type Int) Min(0) skip: number 0; Field(type Int) Min(1) Max(50) take: number 25; }要点InputType()将类映射为 GraphQL input 类型ArgsType()将类映射为一组参数每个字段成为一个独立参数而不是一个嵌套对象因此recipes(skip: Int, take: Int)在 SDL 中是平铺的参数。Length、Min、Max、ArrayMaxSize都来自class-validator库MaxLength限制字符串最大长度Length(30, 255)限制 30255 字符Min/Max限制数值范围ArrayMaxSize限制数组元素个数上限。TypeGraphQL 会自动为InputType与ArgsType的字段执行这些校验校验失败会抛出ArgumentValidationError见 ArgumentValidationError.ts。需要注意命名细节入门文档早期版本写作MaxArraySize(30)而 class-validator 中该装饰器的规范名称是ArrayMaxSize(30)当前仓库 docs/getting-started.md 已采用正确写法。字段默认值skip: number 0、take: number 25会被反映到生成的 SDL 中skip: Int 0、take: Int 25。一个小提示原示例中InputType()类名为NewRecipeDataInput而 resolver 与最终 SDL 中使用NewRecipeInput。默认情况下 GraphQL 输入类型名取自类名可推断该差异来自示例的命名不一致若希望固定输出NewRecipeInput可向InputType传入name参数如InputType(NewRecipeInput)。构建 SchemabuildSchema与emitSchemaFile最后一步是把以上所有装饰器元数据编译为可执行的 GraphQL schema使用buildSchemaconst schema await buildSchema({ resolvers: [RecipeResolver], }); // ...creating express server or sth从源码 buildSchema.ts 可以看到buildSchema接收resolvers非空 resolver 类数组并交给SchemaGenerator.generateFromMetadata生成GraphQLSchema若传入空数组会抛出Empty resolvers array property found in buildSchema options错误。它还支持emitSchemaFile选项传字符串路径、布尔值或配置对象把打印出的 SDL 写入文件默认路径为进程工作目录下的schema.graphql见 getEmitSchemaDefinitionFileOptions。参考 examples/simple-usage/index.tsconst schema await buildSchema({ resolvers: [RecipeResolver], emitSchemaFile: path.resolve(__dirname, schema.graphql), });同时提供同步版本buildSchemaSync见 buildSchema.ts便于在无异步上下文的场景使用。构建完成后打印出的 SDL 正是我们期望的样子type Recipe { id: ID! title: String! description: String creationDate: Date! ingredients: [String!]! } input NewRecipeInput { title: String! description: String ingredients: [String!]! } type Query { recipe(id: ID!): Recipe recipes(skip: Int 0, take: Int 25): [Recipe!]! } type Mutation { addRecipe(newRecipeData: NewRecipeInput!): Recipe! removeRecipe(id: ID!): Boolean! }注意两处自动推导出的细节recipe(id: ID!): Recipe的返回类型是可空的单个查询可能找不到数据方法返回PromiseRecipe但查询结果允许 null而recipes与removeRecipe的结果是非空数组/非空标量。这些可空性规则由returns ...与{ nullable }选项共同决定。在仓库中查看完整可运行示例examples/simple-usage/目录提供了与入门指南同主题的完整可运行版本examples/simple-usage/index.tsbootstrap函数中buildSchema Apollo Server 启动监听 4000 端口并把 SDL 输出到schema.graphqlexamples/simple-usage/recipe.type.ts带description、deprecationReason、getter 计算字段的RecipeObject Typeexamples/simple-usage/recipe.resolver.ts实现ResolverInterfaceRecipe包含recipe/recipes查询、addRecipe变更及一个带Arg默认值的FieldResolverratingsCount(minRate)examples/simple-usage/recipe.input.tsInputType输入类examples/simple-usage/recipe.data.ts内存中的样例数据工厂。更进一步入门指南只是冰山一角接口interfaces、枚举enums、联合类型unions、自定义标量custom scalarsTypeGraphQL 都完整支持此外还有授权检查器auth checker、继承inheritance、字段解析器field resolvers、订阅subscriptions、依赖注入DI container、middleware 与查询复杂度限制等进阶能力。更多完整用例可前往 Examples 章节例如其中展示了 TypeGraphQL 与 TypeORM 的集成方式以及各能力的配套示例目录examples/下按主题组织如authorization/、interfaces-inheritance/、redis-subscriptions/、query-complexity/等方便对照学习。赞分享后端GraphQLAPI设计【免费下载链接】type-graphqlCreate GraphQL schema and resolvers with TypeScript, using classes and decorators!项目地址https://gitcode.com/gh_mirrors/ty/type-graphql点击查看免费下载相关推荐TypeGraphQL入门指南用TypeScript和装饰器构建GraphQL APITypeGraphQL入门指南用TypeScript和装饰器构建GraphQL API TypeGraphQL是一个革命性的开源库通过TypeScript装后端GraphQLAPI设计TypeGraphQL 入门用 TypeScript 类与装饰器构建 GraphQL Schema 与 ResolverTypeGraphQL 入门用 TypeScript 类与装饰器构建 GraphQL Schema 与 Resolver TypeGraphQL 是一个面向后端GraphQLAPI设计Nitro 资源系统完全指南Public Assets、文件内联导入与 Server AssetsNitro 资源系统完全指南Public Assets、文件内联导入与 Server Assets Nitro 内置了一套完整的静态资源与文件资产管理方案覆后端GraphQLAPI设计上一篇SillyTavern终极指南5个简单技巧打造生动AI角色卡片系统下一篇像素字体新选择Fusion Pixel Font 让你的设计瞬间回到80年代创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【日本 6G 三线并进·第 2 篇】光通信 IOWN(上):NICT 430Tbps 与 NTT 200GHz 光电探测器 2026/9/27 23:23:05

【日本 6G 三线并进·第 2 篇】光通信 IOWN(上):NICT 430Tbps 与 NTT 200GHz 光电探测器

【日本 6G 三线并进第 2 篇】光通信 IOWN(上):NICT 430Tbps 与 NTT 200GHz 光电探测器摘要:这是系列第 2 篇,进入光通信线。本文拆解两项物理层极限突破:NICT 如何在标准光纤上实现每秒 430 太比特传输&…

阅读更多 →
在 Visual Studio 中接入 Ace Data Cloud:让 AI 编程助手真正进入开发工作流 2026/9/27 23:23:05

在 Visual Studio 中接入 Ace Data Cloud:让 AI 编程助手真正进入开发工作流

在 AI 编程工具越来越多的今天,很多开发者已经不满足于“只能在网页里和大模型对话”,而是希望把 AI 直接接入自己的 IDE:写代码、解释项目、辅助重构、生成测试、排查报错,都能在熟悉的开发环境里完成。 如果你正在使用 Visual S…

阅读更多 →
5G Massive MIMO原理与工程实践:从波束赋型到DM-RS端口映射 2026/9/27 23:23:05

5G Massive MIMO原理与工程实践:从波束赋型到DM-RS端口映射

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
解决wordpress站标签打开空白:安全排查与SSL证书年审哪家更稳 2026/9/27 23:23:05

解决wordpress站标签打开空白:安全排查与SSL证书年审哪家更稳

解决wordpress站标签打开空白:安全排查与SSL证书年审哪家更稳 自己不会代码想做网站,最怕的就是改个配置,页面直接白屏。这时候找外包问 哪家好 ,对方往往只说重启试试,根本解决不了 WordPress 站标签打开空白…

阅读更多 →
Java面试八股文背了没用,关键在这3点 2026/9/27 23:23:04

Java面试八股文背了没用,关键在这3点

第一点:理解设计动机,而不是记住结论八股文最大的问题是只给结论不给原因。比如“ArrayList默认容量是10”,背下来有什么用?面试官想知道的是:为什么是10?扩容因子为什么是1.5?为什么不是2&…

阅读更多 →
会议室门牌安装方式怎么选,墙面场景适配选型落地指南 2026/9/27 23:22:58

会议室门牌安装方式怎么选,墙面场景适配选型落地指南

在推进企业办公空间数字化升级时,会议室门牌往往是被低估却极易“翻车”的环节。很多项目前期只关注屏幕尺寸、系统功能或显示内容,等到设备到货准备安装时,才发现墙面条件与预设方案严重冲突:精装交付的写字楼不允许随意开槽打孔…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉