我有以下代码片段:

export const NodeInterface = new GraphQLInterfaceType({
  name: 'Node',
  fields: {
    id: {
      type: new GraphQLNonNull(GraphQLID)
    }
  },
  resolveType: (source) => {
    if (source.__tableName === tables.users.getName()) {
      return UserType;
    }
    return PostType;
  }
});


和使用该接口的GraphQLObjectType

export const PostType = new GraphQLObjectType({
  name: 'Post',
  interfaces: [ NodeInterface ],
  fields: {
    id: {
      type: new GraphQLNonNull(GraphQLID),
      resolve: resolveId
    },
    createdAt: {
      type: new GraphQLNonNull(GraphQLString),
    },
    body: {
      type: new GraphQLNonNull(GraphQLString)
    }
  }
});


我必须定义什么接口?

最佳答案

在GraphQL中,接口实现两个目的:


它们确保实现它们的类型也实现特定的字段。例如,这里的Node接口具有一个id字段-这意味着实现Node接口的任何类型都将需要具有id字段(并且id必须是ID标量就像接口中的标量一样。那些参数也是如此-接口字段中的任何参数也都必须存在于实现类型中的匹配字段上。
当一个字段需要两种或多种类型时,可以使用它们。一个字段将始终解析为一种类型或标量,但是,通过使用接口(或并集),我们在架构中指出该字段可以解析为一组类型之一。


假设我们在您的代码段中有一个Node,实现了它的某些类型,以及一个返回Node的查询:

interface Node {
  id: ID!
}

type Foo implements Node {
  id: ID!
  someFooField: String!
  someOtherFooField: Int!
}

type Bar implements Node {
  id: ID!
  someBarField: String!
  someOtherFooField: Int!
}

type Query {
  getNode(id: ID!): Node!
}


在我们的示例中,getNode可以解析为FooBar。当我们编写查询时,我们不知道将解决哪个查询。但是因为我们知道接口需要id字段,所以我们可以编写如下查询:

query OperationName {
  getNode(id: "SOME_ID"){
    id
  }
}


但是,如果我们还需要查询someBarField,则无法执行此操作:

query OperationName {
  getNode(id: "SOME_ID"){
    id
    someBarField
  }
}


因为Foo没有该字段。相反,我们必须利用一个片段,如下所示:

query OperationName {
  getNode(id: "SOME_ID"){
    id
    ... on Bar {
      someBarField
    }
  }
}


然后,将返回someBarField,但前提是该字段解析为类型Bar。如果是Foo,则仅返回ID。同样,您可以从实现相同接口的任何类型请求非共享字段:

query OperationName {
  getNode(id: "SOME_ID"){
    id
    ... on Bar {
      someBarField
    }
    ... on Foo {
      someFooField
    }
  }
}


最后但并非最不重要的一点是,工会的工作方式非常相似。但是,与接口不同,没有为联合定义任何共享字段,因此类型不会“实现”联合,而只是联合的一部分。这意味着在请求返回联合的字段时,由于没有共享字段可请求,因此您将始终必须使用片段。

10-05 20:30
查看更多