
后端GraphQLAPI设计【免费下载链接】type-graphqlCreate GraphQL schema and resolvers with TypeScript, using classes and decorators!项目地址https://gitcode.com/gh_mirrors/ty/type-graphql点击查看免费下载本篇技术指南聚焦 TypeGraphQL 中标量Scalar类型的完整处理机制如何用ID/Int/Float别名简化字段声明、如何编写并使用自定义GraphQLScalarType如 Mongo 的ObjectId、以及内置Date标量的两种序列化格式ISO 字符串与时间戳数字及切换方法。读完本文你将掌握在 TypeGraphQL 项目中声明、反射、映射和自定义任意标量类型的全部实战技巧并理解其底层类型解析原理。内置标量别名AliasesTypeGraphQL 为 3 个 GraphQL 基础标量提供了简写别名方便在Field装饰器中快速声明字段类型Int→GraphQLIntFloat→GraphQLFloatID→GraphQLID这些别名定义在 src/scalars/aliases.ts 中本质就是 graphql 包的对应标量实例的直接再导出import { GraphQLFloat, GraphQLID, GraphQLInt } from graphql; export const Int GraphQLInt; export const Float GraphQLFloat; export const ID GraphQLID;使用别名可以显著减少声明字段类型时的按键次数// 导入别名 import { ID, Float, Int } from type-graphql; ObjectType() class MysteryObject { Field(type ID) readonly id: string; Field(type Int) notificationsCount: number; Field(type Float) probability: number; }其中最后一个字段probability: number可以省略type Float因为 JavaScript 的Number类型在构建 schema 时会自动映射为GraphQLFloat。这一自动反射逻辑实现在 src/helpers/types.ts 的convertTypeIfScalar函数中当装饰器没有显式给出类型函数时TypeGraphQL 会先检查scalarsMap映射表再通过switch将String→GraphQLString、Boolean→GraphQLBoolean、Number→GraphQLFloat、Date→GraphQLISODateTime自动转换。同样地GraphQLString和GraphQLBoolean也不需要别名只要反射机制能够识别它们就会被自动映射ObjectType() class User { Field() name: string; Field() isOld: boolean; }何时必须显式声明 String / Boolean在某些情况下TypeScript 的反射机制无法推断出精确类型此时必须显式声明字符串或布尔标量。典型场景是使用 getter 且返回类型包含undefined时反射出的类型会退化为ObjectObjectType() class SampleObject { Field(type String, { nullable: true }) // TS 反射出的类型是 Object :( get optionalInfo(): string | undefined { if (Math.random() 0.5) { return Gotcha!; } } }此时显式传入 JS 构造函数String或Boolean作为类型函数即可让 schema 正确生成String/Boolean标量。该行为在 tests/functional/scalars.ts 中有完整验证测试同时断言了显式Field(() String)、隐式string属性、显式/隐式Boolean、隐式number属性映射为Float、显式Int等场景下生成的标量名称均符合预期。自定义标量Custom ScalarsTypeGraphQL 完整支持自定义标量类型可以自行创建GraphQLScalarType实例也可以直接导入第三方 npm 库中现成的标量。第一步创建 GraphQLScalarType 实例以 MongoDB 的ObjectId为例自定义标量需要实现三个核心方法分别负责序列化输出、解析输入变量和解析查询字面量import { GraphQLScalarType, Kind } from graphql; import { ObjectId } from mongodb; export const ObjectIdScalar new GraphQLScalarType({ name: ObjectId, description: Mongo object id scalar type, serialize(value: unknown): string { // 校验值类型 if (!(value instanceof ObjectId)) { throw new Error(ObjectIdScalar can only serialize ObjectId values); } return value.toHexString(); // 发送给客户端的值 }, parseValue(value: unknown): ObjectId { // 校验值类型 if (typeof value ! string) { throw new Error(ObjectIdScalar can only parse string values); } return new ObjectId(value); // 来自客户端输入变量的值 }, parseLiteral(ast): ObjectId { // 校验 AST 节点类型 if (ast.kind ! Kind.STRING) { throw new Error(ObjectIdScalar can only parse string values); } return new ObjectId(ast.value); // 来自客户端查询字面量的值 }, });三个方法的职责分工serialize把服务端内部值如ObjectId实例转换成发送给客户端的值如十六进制字符串parseValue把客户端通过 variables 传入的值转换成服务端内部值parseLiteral把客户端查询中内联字面量AST 节点转换成服务端内部值。在仓库的 examples/typegoose/object-id.scalar.ts 中可以找到一份真实可运行的同类实现使用 mongoose 的Types.ObjectId其结构与上面示例完全一致可作为实战参考模板。第二步在字段装饰器中显式使用创建好标量后即可在Field中直接显式引用// 导入前面创建的常量 import { ObjectIdScalar } from ../my-scalars/ObjectId; ObjectType() class User { Field(type ObjectIdScalar) // 显式使用 readonly id: ObjectId; Field() name: string; Field() isOld: boolean; }第三步可选通过 scalarsMap 自动映射如果希望省略Field(type ObjectIdScalar)的显式类型标注可以在buildSchema中通过scalarsMap注册属性类型 ↔ 标量的关联映射ObjectType() class User { Field() // 无需为自定义标量标注类型 readonly id: ObjectId; }只需在buildSchema选项中注册映射表import { ObjectId } from mongodb; import { ObjectIdScalar } from ../my-scalars/ObjectId; import { buildSchema } from type-graphql; const schema await buildSchema({ resolvers, scalarsMap: [{ type: ObjectId, scalar: ObjectIdScalar }], });scalarsMap的底层类型定义在 src/schema/build-context.tsexport interface ScalarsTypeMap { type: Function; scalar: GraphQLScalarType; }该映射表在 schema 构建期间被写入BuildContext.scalarsMaps见 src/schema/build-context.ts随后 src/helpers/types.ts 的convertTypeIfScalar会在自动类型推断前先查表——scalarsMap的优先级高于内置的String/Boolean/Number/Date反射规则。需要注意的是自动映射仅当 TypeScript 反射机制能够识别属性类型时才有效属性类型必须是class构造器函数不能是枚举、联合类型或接口否则反射出的Function无法与映射表中的type精确匹配。该机制在 tests/functional/scalars.ts 中有三组测试覆盖自定义类通过scalarsMap生成Custom标量、Date映射为GraphQLTimestamp后生成Timestamp标量、以及用自定义标量覆盖默认Date映射的覆盖overwrite场景。此外 tests/helpers/customScalar.ts 展示了最小可用的自定义标量定义方式。Date 标量ISO 格式与时间戳格式TypeGraphQL 为Date类型内置了两套可直接使用的标量均导出自type-graphql包底层实现来自graphql-scalarsnpm 包GraphQLISODateTimeISO 格式字符串例如2023-05-19T21:04:39.573ZGraphQLTimestamp基于时间戳的数字例如1518037458374。两者的再导出定义位于 src/scalars/index.tsexport * from ./aliases; export { GraphQLTimestamp, GraphQLDateTimeISO as GraphQLISODateTime } from graphql-scalars;默认情况下TypeGraphQL 使用 ISO 日期格式——这正是 src/helpers/types.ts 中Date默认映射为GraphQLISODateTime的原因tests/functional/scalars.ts 也断言了默认生成的标量名称为DateTimeISO。如果需要切换到时间戳格式同样通过buildSchema的scalarsMap选项完成import { buildSchema, GraphQLTimestamp } from type-graphql; const schema await buildSchema({ resolvers, scalarsMap: [{ type: Date, scalar: GraphQLTimestamp }], });切换之后字段无需显式声明类型函数Date属性会自动映射为Timestamp标量ObjectType() class User { Field() registrationDate: Date; }当然你也可以使用graphql-scalars或其他 npm 包中任意其他的Date相关标量来替换默认映射只需保证scalarsMap中type: Date指向你选择的GraphQLScalarType实例即可。常见问题与注意事项scalarsMap是全局生效的一旦在buildSchema中配置了scalarsMap其映射关系会影响整个 schema 中所有对应属性类型的推断因此切换Date格式前需确认不会破坏已有字段的预期输出格式。显式声明优先于自动反射当Field中显式传入类型函数时TypeGraphQL 会直接使用该类型而不再执行反射查找这也解释了为何显式String/Boolean总是有效。自定义标量的校验义务在开发者serialize、parseValue、parseLiteral中的类型检查如instanceof、typeof、Kind判断需自行编写出错时抛出Error即可被 GraphQL 执行层捕获。测试即文档tests/functional/scalars.ts 完整覆盖了标量别名、隐式/显式映射、自定义标量的序列化与参数解析、scalarsMap切换日期格式等场景是理解标量行为最直接的参考。总结TypeGraphQL 的标量体系由三层组成内置别名ID/Int/Float负责节省样板代码自动反射String/Boolean/Number/Date负责常规类型的零配置映射scalarsMap映射表负责接入自定义标量与覆盖默认行为。理解convertTypeIfScalar的查找顺序显式类型 →scalarsMap→ 内置 switch 反射即可从容应对任何标量需求无论是接入 MongoDBObjectId、切换Date序列化格式还是引入第三方标量库。赞分享后端GraphQLAPI设计【免费下载链接】type-graphqlCreate GraphQL schema and resolvers with TypeScript, using classes and decorators!项目地址https://gitcode.com/gh_mirrors/ty/type-graphql点击查看免费下载相关推荐TypeGraphQL 标量Scalar完全指南内置别名、Date 标量与自定义标量映射TypeGraphQL 标量Scalar完全指南内置别名、Date 标量与自定义标量映射 TypeGraphQL 允许开发者直接用 TypeScript后端GraphQLAPI设计TypeGraphQL 标量Scalar类型完全指南内置别名、Date 标量与自定义标量version-0.17.1TypeGraphQL 标量Scalar类型完全指南内置别名、Date 标量与自定义标量version 0.17.1 本篇指南以 TypeGraphQ后端GraphQLAPI设计TypeGraphQL 标量类型完全指南内置别名、Date 标量与自定义 GraphQLScalarTypeTypeGraphQL 标量类型完全指南内置别名、Date 标量与自定义 GraphQLScalarType 导读 在 TypeGraphQL 中标量Sc后端GraphQLAPI设计上一篇Dify.AI依赖管理第三方库集成下一篇Ontology Playground 项目全景解析一个纯静态站点如何成为 Fabric IQ 本体建模实验室创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考