apollo icon indicating copy to clipboard operation
apollo copied to clipboard

Problems with explicit types in `useResult` since the result now can be `undefined`

Open tobias-kuendig opened this issue 4 years ago • 2 comments

I do use useResult with explicit types:

const configStatus = useResult<ConfigChangelogQuery, ConfigStatus, ConfigStatus>(
	  result,
	  { changelog: [], error: '' },
	  data => data.configChangelog
)

This worked fine up until 4.0.0-alpha.13 where this change got introduced:

https://github.com/vuejs/vue-apollo/pull/1062/files#diff-6bc7e9678664512fca6286f9a45bc6bdb7f3e02b733c2954ff1fb8210e2f87deR59

I now get this error for about 100 useResult calls in my application:

TS2345: Argument of type 'Ref<ConfigChangelogQuery | undefined>' is not assignable to parameter of type 'Ref<ConfigChangelogQuery>'.
   Type 'ConfigChangelogQuery | undefined' is not assignable to type 'ConfigChangelogQuery'.
     Type 'undefined' is not assignable to type 'ConfigChangelogQuery'.

Obviously, the problem here is the new undefined return type in useQuery. So I am wondering, is there an easy way around this problem without having to change all the useResult calls?

Removing the explicit typing would be an easy fix, but this somehow doesn't look right to me either:

const configStatus = useResult(
	  result, 
	  { changelog: [], error: '' },
	  data => data.configChangelog // data is possibly undefined!
)

The data parameter in the pick function is now of the type ConfigChangelogQuery | undefined. Shouldn't this never be undefined in this case? An undefined result should return the default value object and never trigger the pick function.

What am I missing?

tobias-kuendig avatar Jul 22 '21 08:07 tobias-kuendig

i also encountered this error.

Minimal code:

const { result } = useQuery<SomeQueryType>(someQuery);
const data = useResult<SomeQueryType>(result); <- TS2345: Argument of type 'Ref<SomeQueryType | undefined>' is not assignable to parameter of type 'Ref<SomeQueryType>'.

skix123 avatar Jul 30 '21 15:07 skix123

I worked around this issue for now, by using patch-package to monkey-patch like this:

diff --git a/node_modules/@vue/apollo-composable/dist/useMutation.d.ts b/node_modules/@vue/apollo-composable/dist/useMutation.d.ts
index 5a21214..a6e50af 100644
--- a/node_modules/@vue/apollo-composable/dist/useMutation.d.ts
+++ b/node_modules/@vue/apollo-composable/dist/useMutation.d.ts
@@ -12,7 +12,7 @@ export interface UseMutationOptions<TResult = any, TVariables = OperationVariabl
 declare type DocumentParameter<TResult, TVariables> = DocumentNode | Ref<DocumentNode> | ReactiveFunction<DocumentNode> | TypedDocumentNode<TResult, TVariables> | Ref<TypedDocumentNode<TResult, TVariables>> | ReactiveFunction<TypedDocumentNode<TResult, TVariables>>;
 declare type OptionsParameter<TResult, TVariables> = UseMutationOptions<TResult, TVariables> | Ref<UseMutationOptions<TResult, TVariables>> | ReactiveFunction<UseMutationOptions<TResult, TVariables>>;
 export declare type MutateOverrideOptions<TResult> = Pick<UseMutationOptions<TResult, OperationVariables>, 'update' | 'optimisticResponse' | 'context' | 'updateQueries' | 'refetchQueries' | 'awaitRefetchQueries' | 'errorPolicy' | 'fetchPolicy' | 'clientId'>;
-export declare type MutateResult<TResult> = Promise<FetchResult<TResult, Record<string, any>, Record<string, any>> | null>;
+export declare type MutateResult<TResult> = Promise<FetchResult<TResult, Record<string, any>, Record<string, any>>>;
 export declare type MutateFunction<TResult, TVariables> = (variables?: TVariables | null, overrideOptions?: MutateOverrideOptions<TResult>) => MutateResult<TResult>;
 export interface UseMutationReturn<TResult, TVariables> {
     mutate: MutateFunction<TResult, TVariables>;
diff --git a/node_modules/@vue/apollo-composable/dist/useQuery.d.ts b/node_modules/@vue/apollo-composable/dist/useQuery.d.ts
index 651d747..a2ead08 100644
--- a/node_modules/@vue/apollo-composable/dist/useQuery.d.ts
+++ b/node_modules/@vue/apollo-composable/dist/useQuery.d.ts
@@ -13,20 +13,20 @@ export declare type DocumentParameter<TResult, TVariables = undefined> = Documen
 export declare type VariablesParameter<TVariables> = TVariables | Ref<TVariables> | ReactiveFunction<TVariables>;
 export declare type OptionsParameter<TResult, TVariables> = UseQueryOptions<TResult, TVariables> | Ref<UseQueryOptions<TResult, TVariables>> | ReactiveFunction<UseQueryOptions<TResult, TVariables>>;
 export interface UseQueryReturn<TResult, TVariables> {
-    result: Ref<TResult | undefined>;
+    result: Ref<TResult>;
     loading: Ref<boolean>;
-    networkStatus: Ref<number | undefined>;
+    networkStatus: Ref<number>;
     error: Ref<ApolloError | null>;
     start: () => void;
     stop: () => void;
     restart: () => void;
     forceDisabled: Ref<boolean>;
     document: Ref<DocumentNode>;
-    variables: Ref<TVariables | undefined>;
+    variables: Ref<TVariables>;
     options: UseQueryOptions<TResult, TVariables> | Ref<UseQueryOptions<TResult, TVariables>>;
-    query: Ref<ObservableQuery<TResult, TVariables> | null | undefined>;
-    refetch: (variables?: TVariables) => Promise<ApolloQueryResult<TResult>> | undefined;
-    fetchMore: <K extends keyof TVariables>(options: FetchMoreQueryOptions<TVariables, K> & FetchMoreOptions<TResult, TVariables>) => Promise<ApolloQueryResult<TResult>> | undefined;
+    query: Ref<ObservableQuery<TResult, TVariables> | null>;
+    refetch: (variables?: TVariables) => Promise<ApolloQueryResult<TResult>>;
+    fetchMore: <K extends keyof TVariables>(options: FetchMoreQueryOptions<TVariables, K> & FetchMoreOptions<TResult, TVariables>) => Promise<ApolloQueryResult<TResult>>;
     subscribeToMore: <TSubscriptionVariables = OperationVariables, TSubscriptionData = TResult>(options: SubscribeToMoreOptions<TResult, TSubscriptionVariables, TSubscriptionData> | Ref<SubscribeToMoreOptions<TResult, TSubscriptionVariables, TSubscriptionData>> | ReactiveFunction<SubscribeToMoreOptions<TResult, TSubscriptionVariables, TSubscriptionData>>) => void;
     onResult: (fn: (param: ApolloQueryResult<TResult>) => void) => {
         off: () => void;

ropez avatar Aug 05 '21 13:08 ropez

This might have been fixed in 4475805cb6dd48a1f0bdaa8df60432ebdc9963cd

tobias-kuendig avatar Oct 06 '22 05:10 tobias-kuendig

useResult is deprecated, which solves this issue. Use a computed property instead:

https://github.com/vuejs/apollo/commit/2e65263329fa8c9d30cd681778bf7a8fcc22bfed

tobias-kuendig avatar Feb 14 '23 08:02 tobias-kuendig