Skip to content

Commit

Permalink
Type policy inheritance (#9905)
Browse files Browse the repository at this point in the history
* emptye

* documented typePolicy inheritance

* moves content to advanced topics

* Update docs/source/caching/advanced-topics.mdx

Co-authored-by: alessia <[email protected]>

Co-authored-by: alessia <[email protected]>
  • Loading branch information
jpvajda and alessbell authored Jul 19, 2022
1 parent 46897eb commit fa3c3c9
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 0 deletions.
54 changes: 54 additions & 0 deletions docs/source/caching/advanced-topics.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,60 @@ export class Foo extends Component {
export default withApollo(Foo);
```

## TypePolicy inheritence

JavaScript developers will be familiar with the idea of [inheritance](https://en.m.wikipedia.org/wiki/Inheritance_(object-oriented_programming)) from the `extends` clause of `class` declarations, or possibly from dealing with prototype chains created by `Object.create`.

Inheritance is a powerful code-sharing tool, and it works well with Apollo Client for several reasons:

* `InMemoryCache` already knows about the supertype-subtype relationships (_interfaces and unions_) in your schema, thanks to `possibleTypes`, so no additional configuration is necessary to provide that information.

* Inheritance allows a supertype to provide default configuration values to all its subtypes, including `keyFields` and individual field policies, which can be selectively overridden by subtypes that want something different.

* A single subtype can have multiple supertypes in a GraphQL schema, which is difficult to model using the single inheritance model of classes or prototypes. In other words, supporting multiple inheritance in JavaScript requires building a system something like this one, rather than just reusing built-in language features.

* Developers can add their own client-only supertypes to the `possibleTypes` map, as a way of reusing behavior across types, even if their schema knows nothing about those supertypes.

* The `possibleTypes` map is currently used only for fragment matching purposes, which is an important but fairly small part of what the client does. Inheritance adds another compelling use for `possibleTypes`, and should drastically reduce repetition of `typePolicies` when used effectively.

Here's how type policy inheritance works for `InMemoryCache`, considering the example below:

```ts
const cache = new InMemoryCache({
possibleTypes: {
Reptile: ["Snake", "Turtle"],
Snake: ["Python", "Viper", "Cobra"],
Viper: ["Cottonmouth", "DeathAdder"],
},

typePolicies: {
Reptile: {
// Suppose all our reptiles are captive, and have a tag with an ID.
keyFields: ["tagId"],
fields: {
// Scientific name-related logic can be shared among Reptile subtypes.
scientificName: {
merge(_, incoming) {
// Normalize all scientific names to lower case.
return incoming.toLowerCase();
},
},
},
},

Snake: {
fields: {
// Default to a truthy non-boolean value if we don't know
// whether this snake is venomous.
venomous(status = "unknown") {
return status;
},
},
},
},
});
```

## Refetching queries after a mutation

In certain cases, writing an `update` function to [update the cache after a mutation](../data/mutations/#updating-local-data) can be complex, or even impossible if the mutation doesn't return modified fields.
Expand Down
1 change: 1 addition & 0 deletions docs/source/caching/cache-configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -313,3 +313,4 @@ For most objects in a graph, the `__typename` field is vital for proper identifi
### The `fields` property

The final property within `TypePolicy` is the `fields` property, which enables you to [customize the behavior of individual cached fields](./cache-field-behavior).

0 comments on commit fa3c3c9

Please sign in to comment.