如何为GraphQL Query解析器定义自定义响应接口及适配返回类型?
解决GraphQL Codegen解析器返回类型校验问题
问题背景
使用GraphQL Codegen生成Schema与类型接口时,依赖字段级解析器完成数据格式转换,但Query解析器返回的数据源原始格式({items: [{name: "Item Name"}]})不符合自动生成的Resolvers<Context>["Query"]类型要求,而数据源无法修改,仅能通过Basket字段解析器将items转换为字符串数组。
相关代码与Schema:
Schema定义
type Basket { items: [String!] } type Query { getBasket(clientId: String!): Basket }
Query解析器
const Query: Resolvers<Context>["Query"] = { async getBasket(_, args, ctx) { return ctx.models.Basket.get(args.clientId); // 返回原始格式数据 } };
Basket字段解析器
const Basket: BasketResolvers<Context> = { items(root) { return root?.items?.map(item => item.name); // 转换为Schema要求的字符串数组 } };
解决方案
通过GraphQL Codegen的配置调整,让顶层Query解析器接受数据源原始类型,同时保留字段级解析器的转换逻辑,无需修改模型层或重写类型。
方案1:配置allowParentTypeOverride与类型映射
在codegen.ts(或codegen.yml)中添加以下配置:
import type { CodegenConfig } from '@graphql-codegen/cli'; const config: CodegenConfig = { schema: './schema.graphql', generates: { './src/generated/graphql.ts': { plugins: ['typescript', 'typescript-resolvers'], config: { // 允许解析器返回与Schema定义不一致的父类型 allowParentTypeOverride: true, // 定义数据源原始类型的映射,让Codegen识别 mappers: { Basket: './types#RawBasket', }, }, }, }, }; export default config;
然后在src/types.ts中定义原始数据类型:
export type RawBasket = { items: Array<{ name: string }>; };
方案2:显式指定字段解析器的父类型
如果不想全局启用类型覆盖,可开启useIndexSignature后,在字段解析器中显式声明父类型:
- 修改Codegen配置:
// codegen.ts 中新增配置项 config.generates['./src/generated/graphql.ts'].config.useIndexSignature = true;
- 调整Basket解析器的类型声明:
import type { RawBasket } from '../types'; const Basket: Resolvers<Context>['Basket'] = { items(root: RawBasket) { return root?.items?.map(item => item.name); }, };
核心原理
allowParentTypeOverride配置会让Codegen放松顶层解析器的返回类型校验,允许返回与Schema定义不同的原始数据,由字段级解析器负责后续转换。- 类型映射(
mappers)或显式父类型声明,能让TypeScript正确识别原始数据结构,避免类型报错。
内容的提问来源于stack exchange,提问作者Stretch0
相关产品推荐
相关产品推荐

