vuejs / apollo

🚀 Apollo/GraphQL integration for VueJS
http://apollo.vuejs.org
MIT License
6.02k stars 522 forks source link

No type safety when using a function for reactive variables #1339

Open TheDutchCoder opened 2 years ago

TheDutchCoder commented 2 years ago

Describe the bug When using TypeScript, you lose type safety when using a function to supply the variables:

import { gql } from '@apollo/client'
import { ref } from 'vue'
import { useMutation } from '@vue/apollo-composable'

const LOGOUT = gql`
  mutation Logout($input: LogoutInput!) {
    logout(input: $input) {
      id,
    }
  }
`

interface Logout_logout {
  __typename: "LoginReturn";
  id: string;
}

interface Logout {
  logout: Logout_logout | null;
}

interface LogoutInput {
  id: string;
}

interface LogoutVariables {
  input: LogoutInput;
}

// This works
const { mutate } = useMutation<Logout, LogoutVariables>(LOGOUT, {
  variables: {
    input: {
      id: 'test',
      foo: 'bar', // `foo` will throw an error
    },
  },
})

const id = ref('test')

// This has no type safety in the function
const { mutate: mutate2 } = useMutation<Logout, LogoutVariables>(LOGOUT, () => ({
  variables: {
    input: {
      id: id.value, // ref, so we need to use a function
      foo: 'bar', // `foo` doesn't exist and should throw an error
    },
  },
}))

To Reproduce Steps to reproduce the behavior:

  1. Run the above code
  2. Error should appear in the first mutation, but not the second

Expected behavior Type safety to work when supplying a (mandatory) function

Versions vue: 3.2.20 @vue/apollo-composable: 4.0.0-alpha.16 @apollo/client: 3.5.10

TheDutchCoder commented 2 years ago

The only workaround for this, is to supply the variables when calling the mutation manually, e.g.:

const { mutate } = useMutation<Logout, LogoutVariables>(LOGOUT)

const doThing = () => mutate({
  input: {
    id: 'test',
    foo: 'bar', // throws TS error
  },
})
TheDutchCoder commented 2 years ago

The following also seems like a TS bug:

const variables = ref({ // same issue for `reactive` instead of `ref`
  input: {
    id: 'test',
  },
})

const {
  mutate: logout,
  onError: onErrorLogout,
} = useMutation<Logout, LogoutVariables>(LOGOUT, variables) // throws a TS error, see below

// Argument of type 'Ref<{ input: { id: string; }; }>' is not assignable to parameter of type 'OptionsParameter<Logout, LogoutVariables> | undefined'.