-
Notifications
You must be signed in to change notification settings - Fork 59
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
Inherit types #189
Comments
I'll try to rephrase your problem more abstractly to make sure I understand correctly: You have two interfaces Does that sound right? I wonder whether it would be better to store the subtyping relationship rather than simply copy Maybe your use case could be solved by supporting interfaces implementing other interfaces (an addition to the spec that was recently merged)? |
My use case is a little different than that. In my case, To make it a bit more concrete, these are my interfaces: interface A {
oneGraphId: ID!
}
interface B {
id: ID!
} What I'm looking for is more of a helper to reduce some of the boilerplate of creating my new interface. Since I've already done all of the work to create coercers for interface |
Ah, I see. It sounds like there's some domain knowledge that is not expressed in the schema: I wonder if this is a use case that can be generalised so it's more broadly applicable -- any thoughts on this? I would prefer adding a general capability over a very specific one. |
Do you think it would be possible to give user code more access to the internals for abstract types? I could probably do everything I needed if I had two functions, one that gave me all of the types for an abstract type and another that allowed me to construct an |
Can you try provide suggested types for these two functions? Just to make sure I understand correctly. I haven't thought deeply about it, but I think this approach might run into some typing issues. |
Another way to address this issue is by relaxing the type guarantees around unions and interfaces. It's generally hard to capture these concepts well without a clunky API, and the current one has its warts too. Interfaces implementing other interfaces will only make this harder. I've created a proof of concept on a branch, which relaxes the type guarantees around unions and interfaces. In particular, the type system no longer tries to enforce a correct return value from fields with an interface/union as the output type. This can cause errors at query time if you make a mistake. On the other hand the API is (much?) simpler. Example: let cat = Schema.(obj "Cat" ~fields:(fun _ -> (* ... *)))
let dog = Schema.(obj "Dog" ~fields:(fun _ -> (* ... *)))
let pet = Schema.(union "Pet" Type.[dog; cat])
let named =
Schema.(interface "Named"
Type.[dog; cat]
~fields:(fun _ -> [
abstract_field "name" ~typ:(non_null string) ~args:Arg.[]
]))
let schema =
Schema.(schema [
field "pets"
~typ:(non_null (list (non_null pet)))
~args:Arg.[]
~resolve:(fun _ () -> [ abstract_value cat meow; abstract_value dog fido ])
;
field "named_objects"
~typ:(non_null (list (non_null named)))
~args:Arg.[]
~resolve:(fun _ () -> [ abstract_value cat meow; abstract_value dog fido ]);
]) Would the loss of type safety be worth the simplified interface for you, @dwwoelfel? |
Sorry for the delay. I tried to write the functions I mentioned, but couldn't figure out a way to do it without an error about types escaping their scope. In the end, I just ended up implementing it without any changes to ocaml-graphql-server. https://www.onegraph.com/schema/interface/OneGraphNode
This looks really nice! We're not really taking advantage of the current type safety, anyway. Seems like it should work with mutually recursive objects? let rec cat = lazy Schema.(obj "Cat" ~fields:(fun _ -> (* ... *)))
and dog = lazy Schema.(obj "Dog" ~fields:(fun _ -> (* ... *)))
and pet = lazy Schema.(union "Pet" Type.[(Lazy.force dog); (Lazy.force cat)]) One problem we notice with the current interface/union definers is that we have to remember to call |
Cool, I'll consider moving forward with this 😎
Yes.
Yeah, I've definitely run into that as well. I have an idea for a design that gets rid of |
I'm working on implementing a Node interface for OneGraph. Each of our underlying APIs implements its own node interface, so we have
GitHubNode
,SalesforceNode
,IntercomNode
, etc.To implement the resolver for the
OneGraphNode
, I just need to determine which service thenodeId
is for, then utilize the existing machinery for resolving a node.It would look something like:
It would be really handy if I had a way to convert from the underlying service's node interface to the OneGraph node interface.
Would you be open to a new
inherit_types
function that copied all the types from one interface to another and created a function to coerce from one interface to another?It would look like:
With that function, I could easily construct
gitHubNodeToOneGraphNode
andsalesforceNodeToOneGraphNode
above by doing:The text was updated successfully, but these errors were encountered: