Interfaces#
Interfaces are a special types that other types can implement.
Interfaces are useful when you want to define a common set of fields.
In graphql you can use interfaces types like this:
interface Media {
id: ID!
duration: String!
}
type Audio implements Media {
id: ID!
duration: String!
album: String!
}
type Video implements Media {
id: ID!
duration: String!
thumbnailUrl: String!
}
type Query {
search(text: String!): [Media!]!
}
In hiku you can define interface types like this:
from hiku.graph import Field, Interface
from hiku.types import ID, String,
from hiku.utils import empty_field
Interface('Media', [
Field('id', ID, empty_field),
Field('duration', String, empty_field),
])
Lets look at full example on how to use interfaces in hiku:
from hiku.graph import Field, Graph, Link, Node, Root, Interface
from hiku.types import ID, Integer, String, TypeRef, Sequence, Optional, InterfaceRef
from hiku.utils import empty_field
def search_resolver():
return [
(1, TypeRef['Audio']),
(2, TypeRef['Video']),
]
interfaces = [
Interface('Media', [
Field('id', ID, empty_field),
Field('duration', String, empty_field),
]),
]
GRAPH = Graph([
Node('Audio', [
Field('id', ID, audio_fields_resolver),
Field('duration', String, audio_fields_resolver),
Field('album', String, audio_fields_resolver),
], implements=['Media']),
Node('Video', [
Field('id', ID, video_fields_resolver),
Field('duration', String, video_fields_resolver),
Field('thumbnailUrl', String, video_fields_resolver),
], implements=['Media']),
Root([
Link('search', Sequence(UnionRef['Media']), search_resolver, requires=None),
]),
], interfaces=interfaces)
Lets decode the example above:
Interface
type is defined with a name and a list of fields that any implementation type must contain.Audio
andVideo
types implementMedia
interface - they haveid
andduration
field becauseMedia
interface declares them, and in addition to those shared fields each type has its own fields.Link
type is defined with a return type ofSequence[InterfaceRef['Media']]
search_resolver
returns a list of tuples with an id as a first tuple element and type as a second tuple elementnote that interface fields does need to have a resolver function, but currently this function is not used by hiku engine so you can pass
empty_field
as a resolver function (it may change in the future)
Note
InterfaceRef
is a special type that is used to reference interface types. It is used in the example above to define
the return type of the search link. TypeRef
will not work in this case.
If we run this query:
query {
search(text: "test") {
__typename
id
duration
... on Audio {
album
}
... on Video {
thumbnailUrl
}
}
}
As a result we will get a list of objects with __typename
, id
and duration
fields and fields that are specific
to the type of the object.
[
{
'__typename': 'Audio',
'id': 1,
'duration': '1:20',
'album': 'Cool album',
},
{
'__typename': 'Video',
'id': 2,
'duration': '1:40',
'thumbnailUrl': 'http://example.com/thumbnail.jpg',
},
]
Type narrowing#
Unlike other graphql implementations hiku supports type narrowing without
__resolveType
function. It is possible because hiku knows all possible types
at the link resolution time.