vuejs / apollo

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

useMutation does not allow late variables with typescript #910

Open JohnnyCrazy opened 4 years ago

JohnnyCrazy commented 4 years ago

Describe the bug

In the docs it's stated that you can either directly pass variables to useMutation or pass them once you call the resulting mutate function.

With Typescript, as soon as you specify two type arguments to useMutation, it expects you to pass variables directly to useMutation. It does not allow adding them later, which seems to be a bug to me.

Also, if you just supply one type argument to useMutation, the parameter variables of the resulting mutate function is undefined, not allowing any kind of variables. (Which is expected and correct, I guess)

To Reproduce

import { createComponent, ref } from '@vue/composition-api';
import { useMutation } from '@vue/apollo-composable';

type LoginMutation = {}
type LoginMutationVariables = {
  variable: string,
}

export default createComponent({
  setup() {
    // FAILS HERE: Expected 2 arguments, but got 1.
    const { mutate: login } = useMutation<LoginMutation, LoginMutationVariables>(Login);

    // Require variables here, since they're not passed before? Not sure if possible.
    login({
      variable: 'Hello World',
    });
  }
});

Expected behavior

Allow useMutation with 2 type parameters to accept variables at a later point.

Versions vue: vue@2.6.11 vue-apollo: vue-apollo@3.0.2 apollo-client: apollo-client@2.6.8

JohnnyCrazy commented 4 years ago

And it seems like UseMutationReturn has a wrong return type:

Promise<FetchResult<any, Record<string, any>, Record<string, any>>>

instead of

Promise<FetchResult<TResult, Record<string, any>, Record<string, any>>>

https://github.com/vuejs/vue-apollo/blob/32d1f7568e1a4b72fbe2de4ada6985c65675a84b/packages/vue-apollo-composable/src/useMutation.ts#L38-L40

JohnnyCrazy commented 4 years ago

The following diff (also works with patch-package) could be a solution, can also provide a PR once confirmed.

diff --git a/node_modules/@vue/apollo-composable/dist/useMutation.d.ts b/node_modules/@vue/apollo-composable/dist/useMutation.d.ts
index cb91c21..32b4ded 100644
--- a/node_modules/@vue/apollo-composable/dist/useMutation.d.ts
+++ b/node_modules/@vue/apollo-composable/dist/useMutation.d.ts
@@ -17,10 +17,10 @@ export declare type UseMutationOptionsNoVariables<TResult = any, TVariables = Op
  * `useMutation` options for mutations require variables.
  */
 export interface UseMutationOptionsWithVariables<TResult = any, TVariables = OperationVariables> extends UseMutationOptions<TResult, TVariables> {
-    variables: TVariables;
+    variables?: TVariables;
 }
 export interface UseMutationReturn<TResult, TVariables> {
-    mutate: (variables?: TVariables, overrideOptions?: Pick<UseMutationOptions<any, OperationVariables>, 'update' | 'optimisticResponse' | 'context' | 'updateQueries' | 'refetchQueries' | 'awaitRefetchQueries' | 'errorPolicy' | 'fetchPolicy' | 'clientId'>) => Promise<FetchResult<any, Record<string, any>, Record<string, any>>>;
+    mutate: (variables?: TVariables, overrideOptions?: Pick<UseMutationOptions<any, OperationVariables>, 'update' | 'optimisticResponse' | 'context' | 'updateQueries' | 'refetchQueries' | 'awaitRefetchQueries' | 'errorPolicy' | 'fetchPolicy' | 'clientId'>) => Promise<FetchResult<TResult, Record<string, any>, Record<string, any>>>;
     loading: Ref<boolean>;
     error: Ref<Error>;
     called: Ref<boolean>;
@@ -39,6 +39,10 @@ export declare function useMutation<TResult = any>(document: DocumentNode | Reac
  * Use a mutation that does not require variables.
  */
 export declare function useMutation<TResult = any>(document: DocumentNode | ReactiveFunction<DocumentNode>, options: UseMutationOptionsNoVariables<TResult, undefined> | ReactiveFunction<UseMutationOptionsNoVariables<TResult, undefined>>): UseMutationReturn<TResult, undefined>;
+/**
+ * Use a mutation that requires variables.
+ */
+export declare function useMutation<TResult = any, TVariables extends OperationVariables = OperationVariables>(document: DocumentNode | ReactiveFunction<DocumentNode>): UseMutationReturn<TResult, TVariables>;
 /**
  * Use a mutation that requires variables.
  */
chanlito commented 4 years ago

Yes, I'm facing same issue, if I don't type the variables it shows undefined instead of any.

the-nicolas commented 4 years ago

Is that a bigger issue or whats wrong with the Pull-Requests?

Just started a new project and my plan was to directly use that composition-api, because I really like the way how it works. But getting the same undefined error.

Is it too early to use it...?

JohnnyCrazy commented 4 years ago

I would also appreciate some love for this issue. The PRs exists and it's not a huge/breaking change.

Right now, v4 is not really useable in typescript.

JohnnyCrazy commented 4 years ago

For the time being, I created a fork package apollo-composable-fork

It uses vue alpha instead of the composition API tho. Types for useMutation should work šŸ‘ It uses a slightly modified version of #925

Just have in mind it will be deprecated once we Catch up here

datrinh commented 4 years ago

Quite sad that this is being ignored.