如何配置graphql-codegen仅覆盖Resolver的Parent类型而非返回类型?
如何配置graphql-codegen让Resolver的parent用内部类型同时保留默认返回类型?
问题场景
我们的GraphQL服务里同时存在两种并行类型:
- graphql-codegen生成的Resolver返回类型
- 应用内部使用的自定义实体类型(仅内部使用,不会对外暴露全部字段)
举个例子:
内部定义的Pet接口包含敏感字段birthdate:
interface Pet { petId: string; name: string; birthdate: string; type: 'dog' | 'fish' | 'cat'; }
对应的GraphQL Schema隐藏了birthdate,转而通过它计算对外暴露的age字段:
enum PetType { dog, fish, cat } type Pet { petId: String! name: String! age: Int! type: PetType! } type Query { findPet(petId: String!): Pet }
编写Resolver时遇到问题:age字段的parent参数是graphql-codegen生成的类型,没有birthdate字段导致编译报错;用mappers配置会同时覆盖parent和返回类型,破坏原有生成的返回类型约束;allowParentTypeOverride又需要手动为每个Resolver指定parent类型,效率极低。
解决方案
方案一:通过类型别名批量替换parent类型
利用TypeScript映射类型,批量修改生成的Resolver类型的parent参数类型,同时保留原返回类型:
- 导入生成的Resolver类型和内部类型:
import { Resolver, PetResolver as GeneratedPetResolver, Context } from './generated/graphql'; import { Pet as InternalPet } from './internal-types';
- 创建自定义Resolver类型,替换parent为内部类型:
// 映射生成的PetResolver,将parent类型替换为InternalPet,返回类型保持不变 type PetResolver = { [Key in keyof GeneratedPetResolver]: Resolver< ReturnType<GeneratedPetResolver[Key]>, InternalPet, Context >; };
- 使用自定义类型编写Resolver:
const myPetAgeResolver: PetResolver['age'] = async (parent) => { // 现在可以正常访问内部类型的birthdate字段 return new Date().getFullYear() - new Date(parent.birthdate).getFullYear(); };
方案二:用mappers指定parent类型,手动约束返回类型
通过mappers让parent使用内部类型,同时手动为根Resolver指定生成的返回类型:
- 在
codegen.yml中配置mappers:
generates: src/generated/graphql.ts: plugins: - typescript - typescript-resolvers config: mappers: # 将GraphQL的Pet类型映射到内部的Pet类型 Pet: ./internal-types#Pet
- 根Resolver手动指定返回类型为生成的GraphQL类型:
import { Query, Pet as GeneratedPet } from './generated/graphql'; import { Pet as InternalPet } from './internal-types'; const myRootPetResolver: Query['findPet'] = async (_, args, context): Promise<GeneratedPet> => { const pet = await context.database.findPet(args.petId); // 类型断言,因为内部类型包含生成类型的所有必填字段 return pet as GeneratedPet; };
- 字段Resolver的parent自动变为内部类型:
const myPetAgeResolver = async (parent: InternalPet) => { return new Date().getFullYear() - new Date(parent.birthdate).getFullYear(); };
注意事项
- 确保内部类型包含生成类型的所有字段,避免类型断言或映射时出现不兼容问题
- 方案一无需修改codegen配置,纯TypeScript类型层面处理;方案二更贴近graphql-codegen的原生配置,适合需要全局统一映射的场景
内容的提问来源于stack exchange,提问作者kemicofa
相关产品推荐
相关产品推荐

