在GraphQL Pothos(Next.js)中实现类来源ObjectType的引用类型
解决GraphQL Pothos中类生成ObjectType的引用错误
错误原因分析
你遇到的Ref function String() { [native code] } has not been implemented错误,根源有两个:
- 多余的无效声明:你手动写了
const MoneyType = builder.objectRef<MoneyShape>("Money");,但MoneyShape从未定义,且这行完全没必要——你已经通过builder.objectType(Money)把类转换成了GraphQL类型,不需要额外创建引用。 - 类型定义顺序问题:原代码先定义Cart类型,后定义Money类型,若解开subTotal字段注释,会出现引用未注册类型的问题。
修复方案
按以下步骤修改代码即可解决:
- 删除无效的
objectRef代码
直接删掉这行无意义的声明:
const MoneyType = builder.objectRef<MoneyShape>("Money");
调整类型定义顺序
先定义被依赖的CartItem和Money类型,再定义Cart类型,确保Cart引用Money时类型已完成注册。恢复并修正Cart的subTotal字段
解开subTotal的注释,确保resolve函数返回合法的Money实例,适配现有数据结构。
修改后的完整服务器代码
import { createServer } from '@graphql-yoga/node' import SchemaBuilder from "@pothos/core" import { CartItem, Cart, Money } from 'gql'; const CARTS = [ { id: '1', items: [ { id: '1', name: 'Item 1', price: 10, quantity: 1 }, { id: '2', name: 'Item 2', price: 20, quantity: 2 } ] }, { id: '2', items: [ { id: '3', name: 'Item 3', price: 30, quantity: 3 }, { id: '4', name: 'Item 4', price: 40, quantity: 4 } ] } ] const builder = new SchemaBuilder({}); // 先定义CartItem类型 builder.objectType(CartItem, { name: "CartItem", description: "A cart item", fields: (t) => ({ id: t.exposeString('id', {}), name: t.exposeString('name', {}), price: t.exposeInt('price', {}), quantity: t.exposeInt('quantity', {}), }), }); // 再定义Money类型 builder.objectType(Money, { name: "Money", description: "A money", fields: (t) => ({ amount: t.exposeInt('amount', {}), formatted: t.field({ type: String, resolve: (money) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(money.amount), }), }), }); // 最后定义Cart类型,此时Money已注册完成 builder.objectType(Cart, { name: "Cart", description: "A cart", fields: (t) => ({ id: t.exposeString('id', {}), items: t.field({ type: [CartItem], resolve: (cart) => cart.items ?? [], }), // 恢复subTotal字段 subTotal: t.field({ type: Money, resolve: (cart) => { const total = cart.items?.reduce((acc, item) => acc + item.price * item.quantity, 0) ?? 0; return new Money(total, `$${total}`); } }) }), }); builder.queryType({ fields: (t) => ({ cart: t.field({ type: Cart, nullable: true, args: { id: t.arg.id({ required: true, description: "the id of the cart" }), }, resolve: (_, { id }) => { const cart = CARTS.find((cart) => cart.id === id); if (!cart) { throw new Error(`Cart with id ${id} not found`) } return cart } }), carts: t.field({ type: [Cart], resolve: () => CARTS }), }), }) const server = createServer({ endpoint: '/api', schema: builder.toSchema(), }) export default server;
额外说明
- Pothos会自动关联
builder.objectType传入的类与对应的GraphQL类型,仅在双向引用/前置引用场景下才需要手动使用objectRef,你的场景完全不需要。 - 保持类型定义顺序:被其他类型依赖的类型要优先定义,避免Pothos找不到注册类型的问题。
内容的提问来源于stack exchange,提问作者Wayne
相关产品推荐
相关产品推荐

