Remove Typename Link
Automatically remove __typename fields from variables.
Overview
When reusing data from a query as an argument to another GraphQL operation, __typename
fields can cause errors. To avoid this, you can use the removeTypenameFromVariables
link to automatically remove __typename
fields from variables in operations.
Remove __typename
from all variables
As an example, take the following query. Apollo Client automatically adds __typename
fields for each field selection set.
1const query = gql`
2 query DashboardQuery($id: ID!) {
3 dashboard(id: $id) {
4 id
5 name
6 }
7 }
8`;
9
10const { data } = await client.query({ query, variables: { id: 1 }});
11// {
12// "dashboard": {
13// "__typename": "Dashboard",
14// "id": 1,
15// "name": "My Dashboard"
16// }
17// }
Now let's update this dashboard by sending a mutation to our server. We'll use the dashboard
returned from the previous query as input to our mutation.
1const mutation = gql`
2 mutation UpdateDashboardMutation($dashboard: DashboardInput!) {
3 updateDashboard(dashboard: $dashboard) {
4 id
5 name
6 }
7 }
8`;
9
10await client.mutate({
11 mutation,
12 variables: {
13 dashboard: { ...data.dashboard, name: 'My Updated Dashboard' }
14 }
15});
Without the use of the removeTypenameFromVariables
link, the server will return an error because data.dashboard
still contains the __typename
field.
Usage
You can import and instantiate it like so:
1import { removeTypenameFromVariables } from '@apollo/client/link/remove-typename';
2
3const removeTypenameLink = removeTypenameFromVariables();
Include removeTypeNameLink
anywhere in your link chain before your terminating link
to remove __typename
fields from variables for all operations.
1import { from } from '@apollo/client';
2
3const link = from([removeTypenameLink, httpLink]);
4
5const client = new ApolloClient({
6 link,
7 // ... other options
8});
If you're using directional composition,
for example, to send a subscription to a websocket connection,
place removeTypenameLink
before splitLink
to remove __typename
from variables for all operations.
1import { from, split } from '@apollo/client';
2import { removeTypenameFromVariables } from '@apollo/client/link/remove-typename';
3
4const removeTypenameLink = removeTypenameFromVariables();
5
6const splitLink = split(
7 ({ query }) => {
8 const definition = getMainDefinition(query);
9 return (
10 definition.kind === 'OperationDefinition' &&
11 definition.operation === 'subscription'
12 );
13 },
14 wsLink,
15 httpLink,
16);
17
18const link = from([removeTypenameLink, splitLink]);
19
20const client = new ApolloClient({
21 link,
22 // ... other options
23});
Keep __typename
in JSON scalars
Sometimes, you may need to retain the __typename
field from a query's response—for example, in the case of JSON scalar input fields.
While the GraphQL type validation spec disallows input fields that begin with two underscores (__
), this restriction doesn't apply when the input field is a JSON scalar. (A JSON scalar type accepts raw JSON as input.) You can configure the removeTypenameFromVariables
link to retain __typename
for certain JSON
scalars.
To do so, provide an except
option when instantiating removeTypenameFromVariables
and use the KEEP
sentinel to denote which variables types should keep __typename
. Each key in the except
option should correspond to an input type in your GraphQL schema.
For example, suppose your schema includes a ConfigureDashboardMutation
mutation that takes a JSON
type variable named $dashboardConfig
:
1mutation ConfigureDashboardMutation($dashboardConfig: JSON) {
2 configureDashboard(config: $dashboardConfig) {
3 id
4 }
5}
You can tell the removeTypenameFromVariables
link to keep all __typename
fields for any variable declared as a JSON
type. (Variable types are inferred from the GraphQL query.)
1import { removeTypenameFromVariables, KEEP } from '@apollo/client/link/remove-typename';
2
3const removeTypenameLink = removeTypenameFromVariables({
4 except: {
5 JSON: KEEP
6 }
7});
Note: the JSON scalar type does not need to be literally named
JSON
to be considered a JSON scalar.
When the query moves through the removeTypenameFromVariables
link, the dashboardConfig
variable will be detected as a JSON
scalar type and all __typename
fields are kept intact.
Nested JSON scalar fields in input variables
Not all top-level variables may map to a JSON scalar type. For more complex input object types, the JSON scalar may be found on a nested field. The except
option lets you configure nested fields within these types to keep __typename
intact.
1import { removeTypenameFromVariables, KEEP } from '@apollo/client/link/remove-typename';
2
3const removeTypenameLink = removeTypenameFromVariables({
4 except: {
5 DashboardInput: {
6 config: KEEP
7 }
8 }
9});
Variables declared as type DashboardInput
will have any top-level __typename
fields removed, but keep __typename
for the config
field.
This nesting can be as deep as needed and include as many fields as necessary. Use the KEEP
sentinel to determine where __typename
should be kept.
1import { removeTypenameFromVariables, KEEP } from '@apollo/client/link/remove-typename';
2
3const removeTypenameLink = removeTypenameFromVariables({
4 except: {
5 // Keep __typename for `bar` and `baz` fields on any variable
6 // declared as a `FooInput` type
7 FooInput: {
8 bar: KEEP,
9 baz: KEEP,
10 },
11
12 // Keep __typename for the `baz.qux` field on any variable
13 // declared as a `BarInput` type
14 BarInput: {
15 baz: {
16 qux: KEEP
17 }
18 },
19
20 // Keep __typename on `bar.baz` and `bar.qux.foo` fields for any
21 // variable declared as a `BazInput` type
22 BazInput: {
23 bar: {
24 baz: KEEP,
25 qux: {
26 foo: KEEP
27 }
28 }
29 },
30 }
31});
To keep __typename
for nested fields in arrays, use the same object notation as if the field were an object type.
1import { removeTypenameFromVariables, KEEP } from '@apollo/client/link/remove-typename';
2
3const removeTypenameLink = removeTypenameFromVariables({
4 except: {
5 // Keep __typename on the `config` field for each widget
6 // in the `widgets` array for variables declared as
7 // a `DashboardInput` type
8 DashboardInput: {
9 widgets: {
10 config: KEEP
11 }
12 }
13 }
14});
Options
Name / Type |
Description |
---|---|
| Determines which input types should retain __typename . This maps the input type to the config, which is either the KEEP sentinel or a nested config of fields. |