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.
1 import { RemoveTypenameFromVariablesLink } from "@apollo/client/link/remove-typename";
2
3 const link = new RemoveTypenameFromVariablesLink();Constructor signature
1constructor(
2 options?: RemoveTypenameFromVariablesLink.Options
3): RemoveTypenameFromVariablesLinkUse case
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 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.
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.
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:
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.
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.
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.
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.
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.
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
KEEPsentinel to preserve all__typenamefields, or a nestedKeepTypenameConfigto preserve__typenamefields on a specific field name.
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.
RemoveTypenameFromVariablesLink.KeepTypenameConfigConfiguration 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.
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 }