About the Download

 
 

I want to write this article, because the approach Apollo Client uses for using Unions and Interfaces is unique and caught me by surprise. I think that running though what I had to find out on my own might help others. I think this 5 minute article is worth 8 to 16 hours of your time.

For the simplicity of focusing of point of this article, I will only be focusing on Union types

What are Union Types?

A Union type gives us the ability for one field to contain more than one field. The best way to really think of it, is in terms of Typescript. A union type would be:

 
type Code {
title: String
}

type Image {
name: String
}

type Result = Code | Header;
export type Query {
search: [Result]
}
 

 

As we can see, it is telling us that it can be one, or the other with regards
to data type. So instead of returning irrelevant data, we only return the data
we need.

The Benefits of Union Types

  1. It lightens payloads
  2. It allows for the UI to display backend as is (for instance, when searching, and showing potential results for categories).
  3. Also, it just doesn’t make sense sometimes

Using Union Types with Apollo Client

This is where things start to get really interesting. Using Apollo with unions/interfaces starts to become tricky. In particular, the client has
no idea what is going on from the server side of things. Once we have different sorts of data for a singular query coming back based on the type of data available, Apollo Client will just assume it is a certain type if it returns
all data for a specific type. However, there are nuanced situations where this will not be the case. Apollo therefore made the decision to use something called the the IntrospectionFragmentMatcher.

It looks something like this:

 

It tells Apollo Client for Angular that it expects the above types in the
interface for User. Unfortunately, Apollo Client requires for IntrospectionFragmentMatcher to be used regardless in any situation. This is very cumbersome, because if backend decides to throw something in for an already existing interface, it will cause the backend to break for that query.

I would like to repeat this once again, if you do not have an
IntrospectionFragmentMatcher set up in your app, and backend adds union, or interface types, it will cause that data to break, and it will return an empty
object.

 
fragmentMatcher: new IntrospectionFragmentMatcher({
introspectionQueryResultData: {
__schema: {
types: [
{
kind: ‘UNION’,
name: ‘descriptionBlocks’,
possibleTypes: [
{ name: ‘CodeBlock’ },
{ name: ‘ImageBlock’ },
],
},
],
},
},
})
 

 

Photo by NASA on Unsplash

The Dilemma — Dynamic list of introspectionQueryResultData

In their documentation they recommend that a script be used at build time, that creates a JSON file. It is a pre-built request built into graphql and looks like this:

 
{
__schema {
types {
kind
name
possibleTypes {
name
}
}
}
}
 

 

This JSON file should then be used in the IntrospectionFragmentMatcher.

It should be noted, that one might immediately think, why not go ahead and pull in the data for possibleTypes at runtime, and then use that for the IntrospectionFragmentMatcher? The difficult part about it, is that the way Apollo works for the IntrospectionFragmentMatcher, is that it requires it to be passed into the cache. The cache is created on page load, and then having to update after cache is loaded, well you already missed the boat. So within the context of Apollo Client for Angular, the only way to load in possible types is to go along with the way documentation recommends it.

What to Know Ahead of Time

What would be really helpful to know ahead of time, is that this is an issue
that can only be solved by DevOps. It requires that back end and front end are
built at the same time. That way, they both get pushed only once the new JSON file has been generated by the script. In this situation, there really is no way about it.

Thank you for reading, and I really hope this helps. I honestly just did this so atleast one person besides me doesn’t have to go through this the same way I did, and that perhaps it would produce some clarity around the best way to approach this issue.

Types
Date Created 13/08/2019
Licence MIT
Support Time(in Minutes) 20
Support Details