RemoveTypenameFromVariablesLink

Automatically remove __typename fields from variables.


RemoveTypenameFromVariablesLink is a non-terminating link that automatically removes __typename fields from operation variables to prevent GraphQL validation errors.

When reusing data from a query as input to another GraphQL operation, __typename fields can cause server-side validation errors because input types don't accept fields that start with double underscores (__). RemoveTypenameFromVariablesLink automatically strips these fields from all operation variables.

TypeScript
1 import { RemoveTypenameFromVariablesLink } from "@apollo/client/link/remove-typename";
2
3 const link = new RemoveTypenameFromVariablesLink();

Constructor signature

TypeScript
1constructor(
2  options?: RemoveTypenameFromVariablesLink.Options
3): RemoveTypenameFromVariablesLink

Use case

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 RemoveTypenameFromVariablesLink, the server will return an error because data.dashboard still contains the __typename field.

Usage

Include RemoveTypenameFromVariablesLink anywhere in your link chain before your terminating link to remove __typename fields from variables for all operations.

TypeScript
1import { ApolloLink } from "@apollo/client";
2import { RemoveTypenameFromVariablesLink } from "@apollo/client/link/remove-typename";
3
4const removeTypenameLink = new RemoveTypenameFromVariablesLink();
5const link = ApolloLink.from([removeTypenameLink, httpLink]);
6
7const client = new ApolloClient({
8  link,
9  // ... other options
10});

If you're using directional composition, for example, to send a subscription to a websocket connection, place RemoveTypenameFromVariablesLink before the split link to remove __typename from variables for all operations.

TypeScript
1import { OperationTypeNode } from "graphql";
2import { ApolloLink } from "@apollo/client";
3import { RemoveTypenameFromVariablesLink } from "@apollo/client/link/remove-typename";
4
5const removeTypenameLink = new RemoveTypenameFromVariablesLink();
6
7const splitLink = ApolloLink.split(
8  ({ operationType }) => {
9    return operationType === OperationTypeNode.SUBSCRIPTION;
10  },
11  wsLink,
12  httpLink
13);
14
15const link = ApolloLink.from([removeTypenameLink, splitLink]);
16
17const client = new ApolloClient({
18  link,
19  // ... other options
20});

Keep __typename in JSON scalars

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 RemoveTypenameFromVariablesLink link to retain __typename for certain JSON scalars.

To do so, provide an except option when instantiating RemoveTypenameFromVariablesLink 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 tell RemoveTypenameFromVariablesLink to keep all __typename fields for any variable declared as a JSON type with the KEEP sentinel. Variable types are inferred from the GraphQL query.

TypeScript
1import {
2  RemoveTypenameFromVariablesLink,
3  KEEP,
4} from "@apollo/client/link/remove-typename";
5
6const removeTypenameLink = new RemoveTypenameFromVariablesLink({
7  except: {
8    JSON: KEEP,
9  },
10});

When the query moves through RemoveTypenameFromVariablesLink, the dashboardConfig variable will be detected as a JSON scalar type and all __typename fields are kept intact.

note
The JSON scalar type does not need to be literally named JSON to be considered a JSON scalar.

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 {
2  RemoveTypenameFromVariablesLink,
3  KEEP,
4} from "@apollo/client/link/remove-typename";
5
6const removeTypenameLink = new RemoveTypenameFromVariablesLink({
7  except: {
8    DashboardInput: {
9      config: KEEP,
10    },
11  },
12});

Variables declared as type DashboardInput will have all 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 {
2  RemoveTypenameFromVariablesLink,
3  KEEP,
4} from "@apollo/client/link/remove-typename";
5
6const removeTypenameLink = new RemoveTypenameFromVariablesLink({
7  except: {
8    // Keep __typename for `bar` and `baz` fields on any variable
9    // declared as a `FooInput` type
10    FooInput: {
11      bar: KEEP,
12      baz: KEEP,
13    },
14
15    // Keep __typename for the `baz.qux` field on any variable
16    // declared as a `BarInput` type
17    BarInput: {
18      baz: {
19        qux: KEEP,
20      },
21    },
22
23    // Keep __typename on `bar.baz` and `bar.qux.foo` fields for any
24    // variable declared as a `BazInput` type
25    BazInput: {
26      bar: {
27        baz: KEEP,
28        qux: {
29          foo: KEEP,
30        },
31      },
32    },
33  },
34});

To keep __typename for nested fields in arrays, use the same object notation as if the field were an object type.

TypeScript
1import {
2  RemoveTypenameFromVariablesLink,
3  KEEP,
4} from "@apollo/client/link/remove-typename";
5
6const removeTypenameLink = new RemoveTypenameFromVariablesLink({
7  except: {
8    // Keep __typename on the `config` field for each widget
9    // in the `widgets` array for variables declared as
10    // a `DashboardInput` type
11    DashboardInput: {
12      widgets: {
13        config: KEEP,
14      },
15    },
16  },
17});

Types

RemoveTypenameFromVariablesLink.KeepTypenameConfig

Configuration object that specifies which input types and fields should retain their __typename fields.

This is a recursive configuration where:

  • Keys represent GraphQL input type names or field names

  • Values can be either the KEEP sentinel to preserve all __typename fields, or a nested KeepTypenameConfig to preserve __typename fields on a specific field name.

TypeScript
1 const config: KeepTypenameConfig = {
2   // Keep __typename for all JSON scalar variables
3   JSON: KEEP,
4
5   // For DashboardInput, only keep __typename on the config field
6   DashboardInput: {
7     config: KEEP,
8   },
9
10   // Nested configuration for complex input types
11   UserInput: {
12     profile: {
13       settings: KEEP,
14     },
15   },
16 };

Options for configuring the RemoveTypenameFromVariablesLink.

Properties
Name / Type
Description
RemoveTypenameFromVariablesLink.KeepTypenameConfig

Configuration that determines which input types should retain __typename fields.

Maps GraphQL input type names to configurations. Each configuration can either be the KEEP sentinel, to preserve all __typename fields, or a nested object that specifies which fields should retain __typename.

TypeScript
1 {
2   except: {
3     // Keep __typename for all JSON scalar variables
4     JSON: KEEP,
5
6     // For DashboardInput, remove __typename except for config field
7     DashboardInput: {
8       config: KEEP,
9     },
10
11     // Complex nested configuration
12     UserProfileInput: {
13       settings: {
14         preferences: KEEP,
15       },
16     },
17   },
18 }