type-graphql中如何将createUnionType创建的联合类型配置为InputType
type-graphql 联合类型作为Mutation入参的解决方案
根本原因
GraphQL 官方规范原生不支持联合类型(Union)作为输入类型,仅输出类型可以使用联合定义。你通过 createUnionType 创建的类型本质是输出用的 GraphQL 对象类型,不符合入参要求的输入类型规范,所以会抛出类型识别错误。不存在直接将createUnionType生成的联合类型转为输入类型的方法,只能通过替代方案实现类似效果。
可行实现方案
目前主流的替代方案是使用带鉴别字段的封装InputType来模拟联合输入的效果,实现步骤如下:
- 定义动作类型枚举并注册
import { registerEnumType } from 'type-graphql'; export enum ActionType { CREATE = 'CREATE', UPDATE = 'UPDATE', DELETE = 'DELETE' } // 注册枚举到type-graphql registerEnumType(ActionType, { name: 'ActionType' });
- 分别定义三类操作对应的输入类型
import { InputType, Field } from 'type-graphql'; @InputType() class CreateActionInput { // 替换为创建动作实际需要的字段 @Field() targetName: string; @Field() content: string; } @InputType() class UpdateActionInput { // 替换为更新动作实际需要的字段 @Field() id: string; @Field({ nullable: true }) targetName?: string; @Field({ nullable: true }) content?: string; } @InputType() class DeleteActionInput { // 替换为删除动作实际需要的字段 @Field() id: string; }
- 封装统一的动作输入类型
@InputType() export class ActionInput { @Field(() => ActionType) type: ActionType; @Field(() => CreateActionInput, { nullable: true }) createParams?: CreateActionInput; @Field(() => UpdateActionInput, { nullable: true }) updateParams?: UpdateActionInput; @Field(() => DeleteActionInput, { nullable: true }) deleteParams?: DeleteActionInput; }
你可以配合class-validator的条件校验装饰器,确保对应类型的参数非空,避免业务逻辑出错。
- Mutation中直接使用该封装类型作为入参
@Mutation(() => Boolean) async handleActions( @Arg('userActions', () => [ActionInput]) userActions: ActionInput[] ) { // 业务逻辑中根据type字段判断当前动作类型,读取对应参数即可 for (const action of userActions) { switch(action.type) { case ActionType.CREATE: const createParams = action.createParams; // 执行创建逻辑 break; case ActionType.UPDATE: const updateParams = action.updateParams; // 执行更新逻辑 break; case ActionType.DELETE: const deleteParams = action.deleteParams; // 执行删除逻辑 break; } } return true; }
补充说明
不推荐使用自定义标量实现输入联合,该方式会丢失GraphQL原生的字段类型校验能力,所有参数合法性都需要自行编码校验,维护成本更高。
内容的提问来源于stack exchange,提问作者David Faizulaev
相关产品推荐
相关产品推荐

