Apollo Client Cache: Type-level Merge Policy for Nested Objects Not Being Applied

I’m having an issue with Apollo Client’s cache where my type-level merge policy for CustomFieldValue isn’t being applied when I update a Entry that contains it.

My Setup

Type Structure:

type Entry {
  entryUrn: String!
  customFieldValues: [CustomFieldValue]
  # other fields
}

type CustomFieldValue {
  urn: String!
  # other fields
}

Cache Configuration:

const cache = new InMemoryCache({
  typePolicies: {
    CustomFieldValue: {
      keyFields: ['urn'],
      merge: mergeCustomFieldValue  // Custom merge function for this type
    },
    Entry: {
      keyFields: ['entryUrn'],
    }
  }
});

The Problem:

When I update an Entry (through a mutation or cache write) that contains updated customFieldValues, the mergeCustomFieldValue function defined in my type policy for CustomFieldValue is never called. I expect the type-level merge function to be triggered for each CustomFieldValue object in the array, but this isn’t happening.

Question:

Why isn’t my type-level merge policy for CustomFieldValue being triggered when I update an Entry containing updated customFieldValues? Do I need to add something specific to make nested normalized objects use their type-level merge functions during parent object updates?

Hey @Ali_Hashemi :waving_hand:

So unfortunately you’re running into one quirky behavior of the cache. You can think of a type-level merge function as a shortcut for defining merge functions for all fields that return a record of that type, rather than thinking of them as a merge function that runs for any record that is that type. There is a subtle difference here and thats because of how it behaves with arrays. Since your field returns an array type, it cannot match a __typename property off of it, so your type-level merge function is never called. You’d instead need to define that merge function on the field that returns the array instead.

Its definitely confusing and we plan to change this in v5. I’m sorry I don’t have a better answer for you, but its just an unfortunate quirk of the implementation of the cache today.