You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置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参数类型,同时保留原返回类型:

  1. 导入生成的Resolver类型和内部类型:
import { Resolver, PetResolver as GeneratedPetResolver, Context } from './generated/graphql';
import { Pet as InternalPet } from './internal-types';
  1. 创建自定义Resolver类型,替换parent为内部类型:
// 映射生成的PetResolver,将parent类型替换为InternalPet,返回类型保持不变
type PetResolver = {
  [Key in keyof GeneratedPetResolver]: Resolver<
    ReturnType<GeneratedPetResolver[Key]>,
    InternalPet,
    Context
  >;
};
  1. 使用自定义类型编写Resolver:
const myPetAgeResolver: PetResolver['age'] = async (parent) => {
  // 现在可以正常访问内部类型的birthdate字段
  return new Date().getFullYear() - new Date(parent.birthdate).getFullYear();
};

方案二:用mappers指定parent类型,手动约束返回类型

通过mappers让parent使用内部类型,同时手动为根Resolver指定生成的返回类型:

  1. 在codegen.yml中配置mappers:
generates:
  src/generated/graphql.ts:
    plugins:
      - typescript
      - typescript-resolvers
    config:
      mappers:
        # 将GraphQL的Pet类型映射到内部的Pet类型
        Pet: ./internal-types#Pet
  1. 根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;
};
  1. 字段Resolver的parent自动变为内部类型:
const myPetAgeResolver = async (parent: InternalPet) => {
  return new Date().getFullYear() - new Date(parent.birthdate).getFullYear();
};

注意事项

  • 确保内部类型包含生成类型的所有字段,避免类型断言或映射时出现不兼容问题
  • 方案一无需修改codegen配置,纯TypeScript类型层面处理;方案二更贴近graphql-codegen的原生配置,适合需要全局统一映射的场景

内容的提问来源于stack exchange,提问作者kemicofa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 22:01:18