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

如何在graphql-codegen中体现字段策略read函数的返回类型?

如何让GraphQL Codegen生成的类型匹配Apollo Client字段转换后的类型

问题背景

我们在Apollo Client里配置了这样的类型策略:每次读取User对象时,会把status字段的枚举值转换成UserStatus类的实例:

// 读取时将User对象的status枚举字段替换为UserStatus类实例
const userTypePolicies = {
  User: {
    fields: {
      status: {
        read: (value: STATUS_ENUM) => new UserStatus(value),
      },
    },
  },
};

但目前GraphQL Codegen生成的User类型里,status字段还是STATUS_ENUM类型,没法体现实际运行时的类型转换。怎么调整才能让生成的代码正确反映这个转换行为?


解决方案

1. 用Codegen的类型映射覆盖原类型

借助typescript-apollo-client插件的mappers配置,直接把生成的User类型替换成我们自定义的版本:

  • 在codegen的配置文件(比如codegen.yml)里添加映射规则:
generates:
  src/generated/graphql.ts:
    plugins:
      - "typescript"
      - "typescript-apollo-client"
    config:
      mappers:
        User: ../types#UserWithStatusInstance
  • 然后在../types.ts里定义映射后的类型:
// 导入Codegen生成的原始类型
import { User as GeneratedUser } from './generated/graphql';
import { UserStatus } from './your-user-status-class';

// 替换status字段的类型
export type UserWithStatusInstance = Omit<GeneratedUser, 'status'> & {
  status: UserStatus;
};

这样Codegen生成的所有用到User的地方,都会自动使用我们自定义的UserWithStatusInstance类型。

2. 修改Schema再生成类型

如果需要更通用的方案,可以先修改GraphQL Schema,把User.status的类型换成自定义标量,再映射到UserStatus:

  • 先在Schema里添加自定义标量:
scalar UserStatusScalar
  • 然后在codegen配置里用transformSchema把User.status的类型替换成这个标量,同时配置标量映射:
generates:
  src/generated/graphql.ts:
    plugins:
      - "typescript"
      - "typescript-apollo-client"
    config:
      scalars:
        UserStatusScalar: ../types#UserStatus
    schema:
      - ./your-schema.graphql
      - transformSchema: |
          module.exports = (schema) => {
            const userType = schema.getType('User');
            userType.getFields().status.type = schema.getType('UserStatusScalar');
            return schema;
          };

这样Codegen会直接把User.status生成为UserStatus类型,不需要额外手动覆盖。

3. 直接在业务代码中扩展类型

如果不想改动Codegen配置,也可以在业务代码里直接扩展生成的User类型:

import { User as GeneratedUser } from './generated/graphql';
import { UserStatus } from './your-user-status-class';

// 重新定义User类型,替换status字段
export type User = Omit<GeneratedUser, 'status'> & {
  status: UserStatus;
};

之后在业务代码里统一使用这个自定义的User类型就行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 04:01:07