Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Algebraic interface types #48

Open
charypar opened this issue Jul 14, 2015 · 9 comments
Open

Algebraic interface types #48

charypar opened this issue Jul 14, 2015 · 9 comments
Labels
👻 Needs Champion RFC Needs a champion to progress (See CONTRIBUTING.md) 💭 Strawman (RFC 0) RFC Stage 0 (See CONTRIBUTING.md)

Comments

@charypar
Copy link

As originally discussed in graphql/graphql-js#45, it would be useful to be able to declare a field type to be a combination of interfaces.

As an example use-case, let's say I have an interface

interface Image {
  src: String
}

which represents an image I can display. Some images are stand-alone and I can link to them as a page, but other things share that capability (videos for instance). So I have another interface

interface Linkable {
  url: String
}

Now let's say that all users have profile pictures which are linkable. I'd like to be able to declare something like this

type User {
   profilePicture: Image + Linkable
}

When resolving such type, the only requirement is for the interfaces not to contain the same attributes. From there it should be possible to find the defining interface for each attribute and then the implementing type based on interface type resolution.

@charypar
Copy link
Author

Following on the request for more real-world example: It is actually very similar to the one I used. It's a content fetching API and what I was trying to do were content collections. There are multiple types of collections (Page, Search, List) and then there are specific named collections at the top level (e.g. Editor's picks). Some of those named collections have a url associated to go to the collection specific page and that depends on a) the type of collection it is b) the specific collection (top stories for instance don't have a URL).

So what I'd like to do is have a Collection interface, which defines a collection has a title and items, and a Linkable interface that says there is an url field. Then I could say

queryType {
  top: Collection
  editors: Collection + Linkable
}

Without needing two specific interfaces for Collection and LinkableCollection (which is ok now, but I could imagine adding other "traits" later and things getting out of control). The other reason is I don't really want to leak the specific types up to the top level, because they may change based on where content gets fetched from, but the interface will likely stay the same.

Hope that helps to provide some more context around the idea.

@leebyron
Copy link
Collaborator

Thanks for the more concrete example, this is really interesting.

@alexyiu-elementum
Copy link

Hi, @leebyron,

I have a couple of questions of GraphQL "interfaces".

(1)
I am wondering whether GraphQL allows a single Type implements Multiple Interfaces.
Using the example above, a related Type definition document would look like the following:

type ProfilePicture implements Linkable, Image {
    # skipping field declaration details here 
}

Based on Schema for Schema Introspection result in the RFC under "4.2 Schema Introspection",
https://facebook.github.io/graphql/#sec-Schema-Introspection
it looks like a single Type can implement multiple interfaces.

  # OBJECT only
  interfaces: [__Type!]

However, all the examples of Type definition document in RFC only show the case of implementing a single interface.

While I can find Grammar for Query Document, I cannot find Grammar for Type Definition Document.
"B.3 Query Document"
https://facebook.github.io/graphql/#sec-Appendix-Grammar-Summary.Query-Document
So, it did not help me to confirm whether this is a supported semantic or not.

(2)
Also, can an Interface "extend" from a bunch of other interfaces?
Based on the current comments under "4.2 Schema Introspection", it seems to imply "no".

Background Note :
Under JSON Schema, there is a construct of "allOf".
http://json-schema.org/latest/json-schema-validation.html#anchor82

We have used "allOf" in JSON Schema in a number of projects quite extensively.
From a technology migration viewpoint, it would be nice to allow:
(1) a single "type" "implements" multiple interfaces, and,
(2) a single "interface" "extends" multiple interfaces.

Alex Yiu
https://www.linkedin.com/in/alexyiu

@leebyron
Copy link
Collaborator

Yes, Objects may implement multiple interfaces. The experimental grammar for defining types works exactly the way you assumed, and you're correct in assuming so based on the fact that introspection returns a list of interfaces for an object type.

You can find the work-in-progress grammar for this at #90

Interfaces cannot extend other interfaces. There's no current plan to change this as it adds some avoidable complexity.

@alexyiu-elementum
Copy link

@leebyron .... thank you for confirming this feature and quick turnaround time of answering my questions.

@Cyberlane
Copy link

Cyberlane commented Jan 23, 2017

@leebyron I don't suppose you have an expected ETA on when the multiple interface support is likely to be available?

Also, will this allow me to change my schema to something similar to this?

interface IHaveGPS {
  someSetting: String
  someOtherSetting: String
}

interface IHaveCellular {
  cellSetting: String
}

type GenericGPS implements IHaveGPS {
  someSetting: String
  someOtherSetting: String
}

type SmartPhone implements [IHaveGPS, IHaveCellular] {
  someSetting: String
  someOtherSetting: String
  cellSetting: String
}

type Query {
  findAll: [IHaveGPS, IHaveCellular]
}

@leebyron
Copy link
Collaborator

@Cyberlane, you can currently have an Object type implement as many interfaces as you like (the SmartPhone example) however there are currently no plans to implement intersection types (your findAll example) - for those cases you could use either another Interface which includes both sets of fields, or a Union type

@leebyron leebyron added 💭 Strawman (RFC 0) RFC Stage 0 (See CONTRIBUTING.md) 👻 Needs Champion RFC Needs a champion to progress (See CONTRIBUTING.md) labels Oct 2, 2018
@sangeethasunkari

This comment has been minimized.

@sangeethasunkari

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
👻 Needs Champion RFC Needs a champion to progress (See CONTRIBUTING.md) 💭 Strawman (RFC 0) RFC Stage 0 (See CONTRIBUTING.md)
Projects
None yet
Development

No branches or pull requests

5 participants