如何在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
相关产品推荐
相关产品推荐

