From 7495987fdb5b7ab6d7ea458cceadb4997ac92e5f Mon Sep 17 00:00:00 2001 From: Brian Bugh Date: Mon, 27 Jul 2020 10:07:02 -0500 Subject: [PATCH] fix(ts): allow undefined for optional variables (#962) --- .../vue-apollo-composable/src/useMutation.ts | 35 ++++------------- .../vue-apollo-composable/src/useQuery.ts | 23 +++++++---- .../src/useSubscription.ts | 7 ++++ .../tests/types/useMutation-types.test.ts | 39 +++++++++++++++++-- .../tests/types/useQuery-types.test.ts | 17 ++++++++ .../tests/types/useSubscription-types.test.ts | 27 +++++++++++++ 6 files changed, 109 insertions(+), 39 deletions(-) diff --git a/packages/vue-apollo-composable/src/useMutation.ts b/packages/vue-apollo-composable/src/useMutation.ts index 5825ae1..20962fd 100644 --- a/packages/vue-apollo-composable/src/useMutation.ts +++ b/packages/vue-apollo-composable/src/useMutation.ts @@ -17,31 +17,12 @@ export interface UseMutationOptions< clientId?: string } -/** - * `useMutation` options for mutations that don't use variables. - */ -export type UseMutationOptionsNoVariables< - TResult = any, - TVariables = OperationVariables -> = Omit, 'variables'> +export type MutateOverrideOptions = Pick, 'update' | 'optimisticResponse' | 'context' | 'updateQueries' | 'refetchQueries' | 'awaitRefetchQueries' | 'errorPolicy' | 'fetchPolicy' | 'clientId'> +export type MutateResult = Promise, Record>> +export type MutateFunction = (variables?: TVariables, overrideOptions?: MutateOverrideOptions) => MutateResult -/** - * `useMutation` options for mutations require variables. - */ -export interface UseMutationOptionsWithVariables< - TResult = any, - TVariables = OperationVariables -> extends UseMutationOptions { - variables: TVariables -} - -type MutateOverrideOptions = Pick, 'update' | 'optimisticResponse' | 'context' | 'updateQueries' | 'refetchQueries' | 'awaitRefetchQueries' | 'errorPolicy' | 'fetchPolicy' | 'clientId'> -type MutateResult = Promise, Record>> -export type MutateWithOptionalVariables = (variables?: TVariables, overrideOptions?: MutateOverrideOptions) => MutateResult -export type MutateWithRequiredVariables = (variables: TVariables, overrideOptions?: MutateOverrideOptions) => MutateResult - -export interface UseMutationReturn = MutateWithOptionalVariables> { - mutate: Mutate +export interface UseMutationReturn { + mutate: MutateFunction loading: Ref error: Ref called: Ref @@ -58,7 +39,7 @@ export interface UseMutationReturn( document: DocumentNode | ReactiveFunction, - options?: UseMutationOptionsWithVariables | ReactiveFunction> + options?: UseMutationOptions | ReactiveFunction> ): UseMutationReturn /** @@ -66,8 +47,8 @@ export function useMutation( document: DocumentNode | ReactiveFunction, - options?: UseMutationOptionsNoVariables | ReactiveFunction> -): UseMutationReturn> + options?: UseMutationOptions | ReactiveFunction> +): UseMutationReturn export function useMutation< TResult, diff --git a/packages/vue-apollo-composable/src/useQuery.ts b/packages/vue-apollo-composable/src/useQuery.ts index 85d4063..11fc215 100644 --- a/packages/vue-apollo-composable/src/useQuery.ts +++ b/packages/vue-apollo-composable/src/useQuery.ts @@ -65,6 +65,21 @@ export function useQuery( document: DocumentNode | Ref | ReactiveFunction ): UseQueryReturn +/** + * Use a query that has optional variables but not options + */ +export function useQuery( + document: DocumentNode | Ref | ReactiveFunction +): UseQueryReturn + +/** + * Use a query that has required variables but not options + */ +export function useQuery( + document: DocumentNode | Ref | ReactiveFunction, + variables: TVariables +): UseQueryReturn + /** * Use a query that requires options but not variables. */ @@ -74,14 +89,6 @@ export function useQuery | Ref> | ReactiveFunction> ): UseQueryReturn -/** - * Use a query that requires variables. - */ -export function useQuery( - document: DocumentNode | Ref | ReactiveFunction, - variables: TVariables | Ref | ReactiveFunction -): UseQueryReturn - /** * Use a query that requires variables and options. */ diff --git a/packages/vue-apollo-composable/src/useSubscription.ts b/packages/vue-apollo-composable/src/useSubscription.ts index 79b6f58..5cf03ed 100644 --- a/packages/vue-apollo-composable/src/useSubscription.ts +++ b/packages/vue-apollo-composable/src/useSubscription.ts @@ -66,6 +66,13 @@ export function useSubscription | ReactiveFunction ): UseSubscriptionReturn +/** + * Use a subscription that has optional variables. + */ +export function useSubscription( + document: DocumentNode | Ref | ReactiveFunction +): UseSubscriptionReturn + /** * Use a subscription that requires variables and options. */ diff --git a/packages/vue-apollo-composable/tests/types/useMutation-types.test.ts b/packages/vue-apollo-composable/tests/types/useMutation-types.test.ts index 1d4c79f..6956058 100644 --- a/packages/vue-apollo-composable/tests/types/useMutation-types.test.ts +++ b/packages/vue-apollo-composable/tests/types/useMutation-types.test.ts @@ -1,5 +1,5 @@ import { FetchResult } from "apollo-link"; -import { useMutation, MutateWithOptionalVariables, MutateWithRequiredVariables } from "../../src"; +import { useMutation, MutateFunction } from "../../src"; import { ExampleDocument, ExampleUpdateMutation, @@ -137,6 +137,37 @@ import { assertExactType } from "./assertions"; }); } +// ============================================================================= +// With all types and without variables because the query has optional variables +// - TResult should be the mutation type +// - TVariables should be the variables type +// ============================================================================= +{ + const useMutationAllTyped = useMutation(ExampleDocument); + + useMutationAllTyped.mutate({ id: "2", example: { name: "remix" } }, {}); + + useMutationAllTyped.onDone(param => { + assertExactType | undefined>(param); + assertExactType( + param.data.exampleUpdate + ); + }); +} + +{ + const useMutationAllTyped = useMutation(ExampleDocument); + + useMutationAllTyped.mutate({ id: "2", example: { name: "remix" } }, {}); + + useMutationAllTyped.onDone(param => { + assertExactType | undefined>(param); + assertExactType( + param.data.exampleUpdate + ); + }); +} + // ============================================================================= // With all things typed and with options and variables // - TResult should be the mutation type @@ -170,7 +201,7 @@ import { assertExactType } from "./assertions"; } ); - assertExactType>( + assertExactType>( withVariablesInOptions.mutate ) @@ -193,7 +224,7 @@ import { assertExactType } from "./assertions"; ExampleDocument ); - assertExactType>( + assertExactType>( withNoOptions.mutate ) @@ -236,7 +267,7 @@ import { assertExactType } from "./assertions"; } ); - assertExactType>( + assertExactType>( withNoVariablesInOptions.mutate ) diff --git a/packages/vue-apollo-composable/tests/types/useQuery-types.test.ts b/packages/vue-apollo-composable/tests/types/useQuery-types.test.ts index f923773..55f90dc 100644 --- a/packages/vue-apollo-composable/tests/types/useQuery-types.test.ts +++ b/packages/vue-apollo-composable/tests/types/useQuery-types.test.ts @@ -71,6 +71,23 @@ import { assertExactType } from "./assertions"; ); } +// ============================================================================= +// With all types and without variables because the query has optional variables +// - TResult should be the query type +// - TVariables should be the variables type +// ============================================================================= +{ + const useQueryAllTyped = useQuery(ExampleDocument); + + const useQueryAllTypedResult = useQueryAllTyped.result.value; + assertExactType(useQueryAllTypedResult); + + const useQueryAllTypedVariables = useQueryAllTyped.variables.value; + assertExactType( + useQueryAllTypedVariables + ); +} + // ============================================================================= // With query types, and no variables // - TResult should be the query type diff --git a/packages/vue-apollo-composable/tests/types/useSubscription-types.test.ts b/packages/vue-apollo-composable/tests/types/useSubscription-types.test.ts index a29a909..0b1d19d 100644 --- a/packages/vue-apollo-composable/tests/types/useSubscription-types.test.ts +++ b/packages/vue-apollo-composable/tests/types/useSubscription-types.test.ts @@ -110,6 +110,33 @@ import { assertExactType } from "./assertions"; useSubscription_AllTyped.onResult(result => result?.data?.exampleUpdated.name); } +// ============================================================================= +// With all types and without variables because the query has optional variables +// - TResult should be the subscription type +// - TVariables should be the variables type +// ============================================================================= +{ + const useSubscription_AllTyped = useSubscription< + ExampleUpdatedSubscription, + ExampleUpdatedSubscriptionVariables + >(ExampleDocument); + + // Result type should match the passed in subscription type + const useSubscription_AllTypedResult = useSubscription_AllTyped.result.value; + assertExactType( + useSubscription_AllTypedResult + ); + + // Variables type should match the passed in variables type + const useSubscription_AllTypedVariables = useSubscription_AllTyped.variables.value; + assertExactType( + useSubscription_AllTypedVariables + ); + + // Result data type should be the passed in result + useSubscription_AllTyped.onResult(result => result?.data?.exampleUpdated.name); +} + // ============================================================================= // With subscription types, and no variables // - TResult should be the subscription type