Is it possible to not return any data when using a GraphQL mutation?

Solution 1:

According to this Github issue you cannot return nothing.

You can define a return type which is nullable e.g.

type Mutation {
  addElement(element: ElementData): ID
  removeElement(id: ID): Boolean
}

But I suggest you return the id of the deleted element, because if you want to work with a cached store you have to update the store when the delete mutation has ran successfully.

Solution 2:

(A) Solution with graphql-scalars

The original answer is below.

Here is another one solution with graphql-scalars library:

  1. install npm install graphql-scalars and then
  2. import their Void type: https://www.graphql-scalars.dev/docs/scalars/void

(B) Solution with a custom scalar

Note: design with void-result from mutations goes against "GQL best practices"

This example was written for NodeJS Apollo Framework, but it is pretty easy to convert the implementation for your language/framework

I'm pretty sure: there is an NPM-package named graphql-void but if you don't want to add another one dependency just copy this code.

1. define Void-scalar in your schema

# file: ./schema.gql

scalar Void

2. implement resolver

// file ./scalar-void.js

import { GraphQLScalarType } from 'graphql'

const Void = new GraphQLScalarType({
    name: 'Void',

    description: 'Represents NULL values',

    serialize() {
        return null
    },

    parseValue() {
        return null
    },

    parseLiteral() {
        return null
    }
})
export Void

3. add the resolver to ApolloServer

Add the Void resolver to the options of your instance of Apollo Server:

# file: ./server.js

import { ApolloServer } from 'apollo-server-express'
import { Void } from './scalar-void'

const server = new ApolloServer({
    typeDefs,  // use your schema
    resolvers: {
        Void: Void,
        // ... your resolvers
    },
    
})

4. use Void for your mutations in the schema

Finally, use the new scalar in your schema:

# file: ./schema.gql

type Mutation{
    addElement(element: ElementData): ID
    removeElement(id: ID): Void
}

Solution 3:

If you use TypeScript and graphql-codegen:

  • In the GraphQL schema:

    scalar Void
    
    type Mutation {
      removeElement(id: ID): Void
    }
    
  • In the codegen config for resolvers:

    config:
      scalars:
        Void: "void"
    

With this config TypeScript will ensure that nothing is returned from the removeElement mutation resolver. And the returning value for the mutation will always be null on the GraphQL side.