繁体   English   中英

GraphQL.js-使用接口作为resolveType函数中的默认(备用)类型

[英]GraphQL.js - use Interface as a default (fallback) type in resolveType function

如果提供的类型都不匹配,我试图在resolveType函数中返回泛型。 下面的示例显示了此问题:API就像支持UserTypeMovieType一样工作,直到在数据库中添加BookType (GraphQL模式不支持)。

const {
  graphql,
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLString,
  GraphQLNonNull,
  GraphQLList,
  GraphQLInterfaceType
} = require("graphql");

const DATA = [
  {
    // UserType
    name: "catherine woolf",
    nick: "catherine"
  },
  {
    // MovieType
    name: "cat woman",
    director: "Jack Wolfgang"
  },
  {
    // --- missing type --- (BookType)
    name: "cats secrets",
    author: "Nicky Glace"
  }
];

const resolveType = data => {
  if (data.nick) {
    return UserType;
  }
  if (data.director) {
    return MovieType;
  }
};

const SearchableType = new GraphQLInterfaceType({
  name: "Searchable",
  fields: {
    name: { type: GraphQLString }
  },
  resolveType: resolveType
});

const UserType = new GraphQLObjectType({
  name: "User",
  interfaces: [SearchableType],
  fields: {
    name: { type: GraphQLString },
    nick: { type: GraphQLString }
  }
});

const MovieType = new GraphQLObjectType({
  name: "Movie",
  interfaces: [SearchableType],
  fields: {
    name: { type: GraphQLString },
    director: { type: GraphQLString }
  }
});

const schema = new GraphQLSchema({
  types: [MovieType, UserType, SearchableType],
  query: new GraphQLObjectType({
    name: "RootQueryType",
    fields: {
      search: {
        type: new GraphQLList(SearchableType),
        args: {
          text: { type: new GraphQLNonNull(GraphQLString) }
        },
        resolve(_, { text }) {
          return DATA.filter(d => d.name.indexOf(text) !== -1);
        }
      }
    }
  })
});

const query = `
  {
    search(text: "cat") {
      name
      ... on User {
        nick
      }
      ... on Movie {
        director
      }
    }
  }
`;

graphql(schema, query).then(result => {
  console.log(JSON.stringify(result, null, 2));
});

所以现在这段代码以错误结尾:

“抽象类型Searchable必须在运行时解析为值为RootQueryType.search的对象类型,其值为\\“ [object Object] \\”,接收为\\“ undefined \\”。Searchable类型应提供一个\\“ resolveType \\”函数,或者每个可能的类型应提供\\“ isTypeOf \\”函数。

这不足为奇,因为当前resolveType可能不返回任何类型。

解决方法

板条箱类型包含相同的字段,例如接口SearchableType (1对1的实现):

const _SearchableType = new GraphQLObjectType({
  name: '_Searchable',
  interfaces: [SearchableType],
  fields: {
    name: { type: GraphQLString },
  }
});

使用它作为后备类型:

const resolveType = data => {
  if (data.nick) {
    return UserType;
  }
  if (data.director) {
    return MovieType;
  }
  return _SearchableType;
};

并将其添加到schema定义中的types

types: [MovieType, UserType, SearchableType, _SearchableType],

但是此解决方案的问题是这样的伪_SearchableType在如下文档中的存在:

文档中有问题的_SearchableType

有什么方法可以返回接口SearchableTyperesolveType等效接口吗? 对我而言,关键点是在文档中隐藏了这种“后备类型”。

GraphQL是强类型的,在解决联合和接口时不支持泛型或某种“后备”机制。 归根结底,如果您的基础数据层返回的是您尚未在架构中实现的某种类型,那么最简单的解决方案是将该类型添加到架构中。 迁移到数据库和更改架构应该同时进行。

如果要从存储层派生架构,建议您使用PostGraphile (以前称为PostGraphQL)之类的工具。

就是说,如果您打算使用一种解决方法,则可以使用现有类型之一:

const resolveType = data => {
  if (data.nick) {
    return UserType
  }
  return MovieType
}

现在,只要您在界面(而不是其中一种类型)上进行查询,一本书的名称仍然可以访问。 这种方法的唯一缺点是,将为书籍返回特定于电影的字段,并将其解析为null,但这不会引起任何问题,除非在您的模式中将它们明确定义为非null。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM