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

GraphQL联合类型resolveType替代方案及报错排查求助

问题描述

我希望通过单个GraphQL查询返回byte字段的不同数据类型(字符串或数组),但遇到报错:

'Abstract type "GetRecordsWrapper" must resolve to an Object type at runtime for field "Query.records". Either the "GetRecordsWrapper" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.'

我已在Resolver类中添加__resolveType函数,但错误仍存在。相关代码如下:

Records Resolver

import { Resolver, Query, Mutation, Args, Subscription } from '@nestjs/graphql';
import { RecordsService } from './records.service';

import { PubSub } from 'graphql-subscriptions';
import { CreateRecordInput, UpdateRecordInput} from '../graphql';

const pubSub = new PubSub();


@Resolver('Record')
export class RecordsResolver {
  constructor(private readonly recordsService: RecordsService) {}

  __resolveType(obj: any) {
    if (typeof obj.byte === 'string') {
      return 'HexByteStringResponse';
    }
    if (Array.isArray(obj.byte)) {
      return 'ByteArrayResponse';
    }
    return null;
  }

  @Query('records')
  async records(@Args('format') args: "byte" | "array"): Promise<any> {
    return this.recordsService.findAll(args);
  }
}

Records Service

import { Injectable } from '@nestjs/common';
import { Record } from '@prisma/client';

import { PrismaService } from '../prisma/prisma.service';
import { CreateRecordInput, UpdateRecordInput, GetRecordsWrapper, HexByteStringResponse, ByteArrayResponse } from 'src/graphql';


@Injectable()
export class RecordsService {
  constructor(private prisma: PrismaService) {}

  async findAll(format: "byte" | "array"): Promise<GetRecordsWrapper[]> {
    const records = await this.prisma.record.findMany({
      include: {
        provider: true,
      },
    });
  
    return records.map(record => {
      if (format === "byte") {
        return {
          ...record,
          byte: `0x${record.byte.toString('hex')}`,
        } as HexByteStringResponse;
      } else {
        return {
          ...record,
          byte: Array.from(record.byte),
        } as ByteArrayResponse;
      }
    });
  }
}

GraphQL Schema

scalar DateTime
scalar Bytes
scalar Provider

type Record {
  id: ID!
  byte: Bytes!
  sendedAt: DateTime!
  createdAt: DateTime!
  provider: Provider!
}

type HexByteStringResponse {
  id: ID!
  byte: String!
  sendedAt: DateTime!
  createdAt: DateTime!
  provider: Provider!
}

type ByteArrayResponse {
  id: ID!
  byte: [Int!]!
  sendedAt: DateTime!
  createdAt: DateTime!
  provider: Provider!
}

union GetRecordsWrapper = HexByteStringResponse | ByteArrayResponse

type Query {
  records(format: String!): [GetRecordsWrapper]!
  record(id: String!): GetRecordsWrapper
  recordsWrapper(type: String!): GetRecordsWrapper
}

请问是否有GraphQL联合类型resolveType的替代方案,或如何解决该报错?


解决方案

修复当前resolveType不生效的问题

你当前的__resolveType函数绑定到了Record类型的Resolver上,但它实际属于联合类型GetRecordsWrapper,需要为该联合类型单独创建Resolver:

  1. 创建联合类型专属Resolver:
import { Resolver } from '@nestjs/graphql';

@Resolver('GetRecordsWrapper')
export class GetRecordsWrapperResolver {
  __resolveType(obj: any) {
    if (typeof obj.byte === 'string') {
      return 'HexByteStringResponse';
    }
    if (Array.isArray(obj.byte)) {
      return 'ByteArrayResponse';
    }
    return null;
  }
}
  1. 将这个新Resolver添加到对应模块的providers数组中,确保NestJS能加载到它。

  2. 原RecordsResolver仅保留查询逻辑即可,删除其中的__resolveType函数。

替代方案:使用isTypeOf函数

如果不想维护联合类型的resolveType,可以给每个具体类型添加isTypeOf函数来识别类型:

  1. 为HexByteStringResponse创建Resolver:
import { Resolver } from '@nestjs/graphql';

@Resolver('HexByteStringResponse')
export class HexByteStringResponseResolver {
  isTypeOf(obj: any) {
    return typeof obj.byte === 'string';
  }
}
  1. 为ByteArrayResponse创建Resolver:
import { Resolver } from '@nestjs/graphql';

@Resolver('ByteArrayResponse')
export class ByteArrayResponseResolver {
  isTypeOf(obj: any) {
    return Array.isArray(obj.byte);
  }
}
  1. 将这两个Resolver添加到模块的providers中,即可替代联合类型的resolveType逻辑。

额外检查点

  • 确保RecordsService返回的每个对象的byte字段类型严格匹配:格式为byte时返回字符串,array时返回数组,避免混合类型导致解析失败。
  • 确认GraphQL Schema中联合类型GetRecordsWrapper的定义正确,包含所有可能的子类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 14:05:54