GraphQL 接口:[interface] 需要 "fieldname" 但 [type] 没有提供

GraphQL Interface: [interface] expects "fieldname" but [type] does not provide it

我有以下原因。我调用了多个 API 的网上商店。每个网上商店都有自己的 GraphQLObjectType,如下面的代码所示。

我目前的类型代码:

// Amazon
const AmazonType = new GraphQLObjectType({
    name: 'amazon',
      fields: () => ( {
        isbn: { type : GraphQLString},
        title: { type: GraphQLString },
        author: { type: GraphQLString},
        publisher: { type: GraphQLString},
    })
});

// itunes
const ItunesType = new GraphQLObjectType({
    name: 'itunes',
    fields: () => ( {
        isbn: { type: GraphQLString },
        title: { type: GraphQLString },
        author: { type: GraphQLString },
        publisher: { type: GraphQLString },
    })
});

// query
const checkStores = new GraphQLObjectType({
  name:'checkBookInStores',
  fields: () => ( {
    isbn: {
      type: GraphQLString,
    },
    itunes: {
      type: ItunesType,
      resolve(parentValue,args){
        //console.log(parentValue);
        data = itunes.getMetadataItunes(parentValue.isbn);
        return data;
      }
    },
    amazon: {
      type: AmazonType,
      resolve(parentValue, args) {
        //console.log(parentValue);
        data = amazon.getMetadataAmazon(parentValue.isbn);
        return data;
      }
    },
  })
});

//RootQuery
const RootQuery = new GraphQLObjectType({
  name:'RootQuery',
  fields:() =>( {
    checkStores: {
      type: new GraphQLList(checkStores),
      args: {
        id: { type: new GraphQLList(GraphQLString),
      },
      resolve: function (_, {id}) {
        var data = [];
        for(var i = 0; i < id.length; i++){
          var record = {
            "isbn": id[i],
          };
          data.push(record);
        }
        return data;
      }
    }
  })
});

//schema
module.exports = new GraphQLSchema({
  query: RootQuery
});

但是,我想制作一个界面,因为我一遍又一遍地使用所有这些字段。我不想重复自己。

我正在尝试实现一个接口(以 issue 为例),但出现以下错误:

"Error: \"metadata\" expects field \"isbn\" but \"itunes\" does not provide it.",

新密码:

// interface
const MetadataType = new GraphQLInterfaceType({
  name: 'metadata',
  fields: () => ({
    isbn: { type: GraphQLString },
    title: { type: GraphQLString },
    author: { type: GraphQLString },
    publisher: { type: GraphQLString },
  }),
  resolveType: (value) => {
    console.log('value resolvetype:', value)
     if (value instanceof ItunesType) {
       return ItunesType;
     }
     else {
       return null;
     }
   },
  });

// itunes
const ItunesType = new GraphQLObjectType({
  name: 'itunes',
  interfaces: [MetadataType],
  fields: () => ({
    name: { type: GraphQLString}
  }),
  isTypeOf: (value) => value instanceof ItunesType,
});

扩展一个接口基本上就是 "this Type will contain these fields" 并且 GraphQL 将在编译您的模式时强制执行该规则。不幸的是,这些字段仍然必须为扩展接口的每种类型显式定义——GraphQL 中没有类型继承。

如果您想避免重复自己,唯一可以做的就是利用您的字段定义只是 return 一个对象这一事实:

const commonFields = {
  isbn: { type: GraphQLString },
  title: { type: GraphQLString },
  author: { type: GraphQLString },
  publisher: { type: GraphQLString },
};
const AmazonType = new GraphQLObjectType({
  name: 'amazon',
  fields: () => commonFields,
});
const ItunesType = new GraphQLObjectType({
    name: 'itunes',
    fields: () => commonFields,
});

如果您有特定于单一类型的附加字段,您还可以执行以下操作:

Object.assign({
  amazonOnlyField: { type: GraphQLString },
}, commonFields)

最后,如果你真的想要类型继承,你可以考虑使用补充库like GraphQL S2S