Elvira
Elvira

Reputation: 1440

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

I have the following casus. I make calls to multiple API's of webstores. Each webstore has a his own GraphQLObjectType, as can be seen in the code below.

Code of my current types:

// 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
});

However, I want to make a interface to, because I use all those fieldsover and over again. I don't want to repeat myself.

I'm trying to implement an interface (by looking at this issue as an example) but I'm getting the following error:

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

The new code:

// 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,
});

Upvotes: 3

Views: 3097

Answers (1)

Daniel Rearden
Daniel Rearden

Reputation: 84857

Extending an Interface basically says "this Type will contain these fields" and GraphQL will enforce that rule when compiling your schema. Unfortunately, those fields still have to be explicitly defined for every type that extends the Interface -- there is no type inheritance in GraphQL.

If you want to avoid repeating yourself, the only thing you can do is take advantage of the fact that your field definitions simply return an object:

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,
});

If you had additional fields that were specific to a single type, you could also do something like:

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

Lastly, if you really want type inheritance, you could look into using a supplementary library like GraphQL S2S.

Upvotes: 6

Related Questions