GraphQL 接口:[interface] 需要“fieldname”,但 [type] 不提供它

Elv*_*ra 3 interface graphql graphql-js

我有以下理由。我调用网上商店的多个 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
});
Run Code Online (Sandbox Code Playgroud)

但是,我想创建一个接口,因为我一遍又一遍地使用所有这些字段。我不想重复自己。

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

"错误:\"元数据\"需要字段\"isbn\",但\"itunes\"不提供它。",

新代码:

// 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,
});
Run Code Online (Sandbox Code Playgroud)

Dan*_*den 5

扩展接口基本上是说“这个类型将包含这些字段”,GraphQL 将在编译模式时强制执行该规则。不幸的是,仍然必须为扩展接口的每种类型显式定义这些字段——GraphQL 中没有类型继承。

如果您想避免重复,您唯一能做的就是利用字段定义仅返回一个对象的事实:

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,
});
Run Code Online (Sandbox Code Playgroud)

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

Object.assign({
  amazonOnlyField: { type: GraphQLString },
}, commonFields)
Run Code Online (Sandbox Code Playgroud)

最后,如果您确实想要类型继承,您可以考虑使用补充库,例如 GraphQL S2S