如何在Apollo Server中共享自定义typeDefs、枚举及Message类型?
在Apollo Server中共享自定义TypeDefs与枚举,解决重复类型定义问题
嘿,我来帮你搞定这个问题!你遇到的There can be only one type named "Message"报错,本质是GraphQL的Schema不允许同名类型被重复定义——你在user和product的typeDefs里各写了一遍Message,自然会冲突。下面分两部分讲清楚怎么共享类型和枚举:
一、共享自定义TypeDefs(以Message为例)
核心思路是把公共类型抽离到单独文件,再在业务模块中引用,最后合并所有TypeDefs到Apollo Server。
步骤1:抽离公共类型
新建一个专门存放公共类型的文件,比如common.typeDefs.js,把Message类型只在这里定义一次:
# common.typeDefs.js type Message { message: String! }
步骤2:修改业务模块的TypeDefs
在user和product的TypeDefs里,只保留各自的业务逻辑,不要再重复定义Message,直接引用即可:
# user.typeDefs.js type Mutation { logout: Message! # 直接用公共的Message类型 }
# product.typeDefs.js type Mutation { addProduct(name: String!, price: Float!): Message! # 同样引用公共类型 }
步骤3:合并TypeDefs到Apollo Server
初始化Apollo Server时,把公共TypeDefs和业务TypeDefs放在一个数组里传入,Apollo会自动合并成一个合法的Schema:
const { ApolloServer } = require('@apollo/server'); const { startStandaloneServer } = require('@apollo/server/standalone'); // 导入所有TypeDefs const commonTypeDefs = require('./common.typeDefs'); const userTypeDefs = require('./user.typeDefs'); const productTypeDefs = require('./product.typeDefs'); // 合并Resolver(注意:Message类型不需要单独写Resolver,只要业务Mutation返回对应结构即可) const resolvers = { Mutation: { logout: () => ({ message: 'Logout successful!' }), addProduct: (_, { name, price }) => ({ message: `Product "${name}" added successfully!` }) } }; // 初始化Server const server = new ApolloServer({ typeDefs: [commonTypeDefs, userTypeDefs, productTypeDefs], resolvers, }); // 启动服务 startStandaloneServer(server, { listen: { port: 4000 } }) .then(({ url }) => console.log(`Server ready at ${url}`));
这样就能完美解决重复定义的问题啦!
二、共享枚举类型
共享枚举的逻辑和共享自定义类型完全一致:
步骤1:在公共文件中定义枚举
还是在common.typeDefs.js里添加枚举:
# common.typeDefs.js type Message { message: String! } # 新增共享枚举 enum ProductStatus { IN_STOCK OUT_OF_STOCK DISCONTINUED }
步骤2:在业务模块中引用
比如在product的TypeDefs里使用这个枚举:
# product.typeDefs.js type Product { id: ID! name: String! status: ProductStatus! # 直接引用公共枚举 } type Mutation { addProduct(name: String!, price: Float!): Message! }
步骤3:合并到Server
同样把包含枚举的公共TypeDefs加入数组,Apollo会自动处理枚举的共享。
三、额外小提示
- 如果你的项目用ES Modules(
import/export),只需要把require换成import即可,逻辑完全相同 - 如果你用
graphql-tag的gql模板字符串定义TypeDefs,抽离和合并的方式也一样——把公共的gql模板单独导出,再和业务模板一起放进数组 - 确保所有公共类型/枚举只在一个地方定义,其他地方只做引用,避免重复
内容的提问来源于stack exchange,提问作者Mustanish Altamash
相关产品推荐
相关产品推荐

