Since 3.8.0

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.

TypeScript
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.

TypeScript
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:

TypeScript
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.

TypeScript
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.

TypeScript
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:

GraphQL
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.)

TypeScript
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.

TypeScript
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.

TypeScript
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.

TypeScript
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
except
KeepTypenameConfig
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.
Feedback

Edit on GitHub

Forums