Skip to content

Commit

Permalink
fix(ts): allow undefined for optional variables (#962)
Browse files Browse the repository at this point in the history
  • Loading branch information
bbugh committed Jul 27, 2020
1 parent 4a5b843 commit 7495987
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 38 deletions.
35 changes: 8 additions & 27 deletions packages/vue-apollo-composable/src/useMutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<UseMutationOptions<TResult, TVariables>, 'variables'>

/**
* `useMutation` options for mutations require variables.
*/
export interface UseMutationOptionsWithVariables<
TResult = any,
TVariables = OperationVariables
> extends UseMutationOptions<TResult, TVariables> {
variables: TVariables
}

type MutateOverrideOptions = Pick<UseMutationOptions<any, OperationVariables>, 'update' | 'optimisticResponse' | 'context' | 'updateQueries' | 'refetchQueries' | 'awaitRefetchQueries' | 'errorPolicy' | 'fetchPolicy' | 'clientId'>
type MutateResult<TResult> = Promise<FetchResult<TResult, Record<string, any>, Record<string, any>>>
export type MutateWithOptionalVariables<TResult, TVariables> = (variables?: TVariables, overrideOptions?: MutateOverrideOptions) => MutateResult<TResult>
export type MutateWithRequiredVariables<TResult, TVariables> = (variables: TVariables, overrideOptions?: MutateOverrideOptions) => MutateResult<TResult>
export type MutateOverrideOptions = Pick<UseMutationOptions<any, OperationVariables>, 'update' | 'optimisticResponse' | 'context' | 'updateQueries' | 'refetchQueries' | 'awaitRefetchQueries' | 'errorPolicy' | 'fetchPolicy' | 'clientId'>
export type MutateResult<TResult> = Promise<FetchResult<TResult, Record<string, any>, Record<string, any>>>
export type MutateFunction<TResult, TVariables> = (variables?: TVariables, overrideOptions?: MutateOverrideOptions) => MutateResult<TResult>

export interface UseMutationReturn<TResult, TVariables, Mutate extends MutateWithOptionalVariables<TResult, TVariables> = MutateWithOptionalVariables<TResult, TVariables>> {
mutate: Mutate
export interface UseMutationReturn<TResult, TVariables> {
mutate: MutateFunction<TResult, TVariables>
loading: Ref<boolean>
error: Ref<Error>
called: Ref<boolean>
Expand All @@ -58,16 +39,16 @@ export interface UseMutationReturn<TResult, TVariables, Mutate extends MutateWit
*/
export function useMutation<TResult = any, TVariables extends OperationVariables = OperationVariables>(
document: DocumentNode | ReactiveFunction<DocumentNode>,
options?: UseMutationOptionsWithVariables<TResult, TVariables> | ReactiveFunction<UseMutationOptionsWithVariables<TResult, TVariables>>
options?: UseMutationOptions<TResult, TVariables> | ReactiveFunction<UseMutationOptions<TResult, TVariables>>
): UseMutationReturn<TResult, TVariables>

/**
* Use a mutation with variables, but without a default.
*/
export function useMutation<TResult = any, TVariables extends OperationVariables = OperationVariables>(
document: DocumentNode | ReactiveFunction<DocumentNode>,
options?: UseMutationOptionsNoVariables<TResult, undefined> | ReactiveFunction<UseMutationOptionsNoVariables<TResult, undefined>>
): UseMutationReturn<TResult, TVariables, MutateWithRequiredVariables<TResult, TVariables>>
options?: UseMutationOptions<TResult, undefined> | ReactiveFunction<UseMutationOptions<TResult, undefined>>
): UseMutationReturn<TResult, TVariables>

export function useMutation<
TResult,
Expand Down
21 changes: 14 additions & 7 deletions packages/vue-apollo-composable/src/useQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,27 @@ export function useQuery<TResult = any>(
): UseQueryReturn<TResult, undefined>

/**
* Use a query that requires options but not variables.
* Use a query that has optional variables but not options
*/
export function useQuery<TResult = any, TVariables extends undefined = undefined>(
document: DocumentNode | Ref<DocumentNode> | ReactiveFunction<DocumentNode>,
variables: TVariables,
options: UseQueryOptions<TResult, TVariables> | Ref<UseQueryOptions<TResult, TVariables>> | ReactiveFunction<UseQueryOptions<TResult, TVariables>>
export function useQuery<TResult = any, TVariables extends OperationVariables = OperationVariables>(
document: DocumentNode | Ref<DocumentNode> | ReactiveFunction<DocumentNode>
): UseQueryReturn<TResult, TVariables>

/**
* Use a query that requires variables.
* Use a query that has required variables but not options
*/
export function useQuery<TResult = any, TVariables extends OperationVariables = OperationVariables>(
document: DocumentNode | Ref<DocumentNode> | ReactiveFunction<DocumentNode>,
variables: TVariables | Ref<TVariables> | ReactiveFunction<TVariables>
variables: TVariables
): UseQueryReturn<TResult, TVariables>

/**
* Use a query that requires options but not variables.
*/
export function useQuery<TResult = any, TVariables extends undefined = undefined>(
document: DocumentNode | Ref<DocumentNode> | ReactiveFunction<DocumentNode>,
variables: TVariables,
options: UseQueryOptions<TResult, TVariables> | Ref<UseQueryOptions<TResult, TVariables>> | ReactiveFunction<UseQueryOptions<TResult, TVariables>>
): UseQueryReturn<TResult, TVariables>

/**
Expand Down
7 changes: 7 additions & 0 deletions packages/vue-apollo-composable/src/useSubscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ export function useSubscription<TResult = any, TVariables extends OperationVaria
variables: TVariables | Ref<TVariables> | ReactiveFunction<TVariables>
): UseSubscriptionReturn<TResult, TVariables>

/**
* Use a subscription that has optional variables.
*/
export function useSubscription<TResult = any, TVariables extends OperationVariables = OperationVariables>(
document: DocumentNode | Ref<DocumentNode> | ReactiveFunction<DocumentNode>
): UseSubscriptionReturn<TResult, TVariables>

/**
* Use a subscription that requires variables and options.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FetchResult } from "apollo-link";
import { useMutation, MutateWithOptionalVariables, MutateWithRequiredVariables } from "../../src";
import { useMutation, MutateFunction } from "../../src";
import {
ExampleDocument,
ExampleUpdateMutation,
Expand Down Expand Up @@ -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<ExampleUpdateMutation, ExampleUpdateMutationVariables>(ExampleDocument);

useMutationAllTyped.mutate({ id: "2", example: { name: "remix" } }, {});

useMutationAllTyped.onDone(param => {
assertExactType<typeof param, FetchResult<ExampleUpdateMutation> | undefined>(param);
assertExactType<typeof param.data.exampleUpdate, ExampleUpdatePayload>(
param.data.exampleUpdate
);
});
}

{
const useMutationAllTyped = useMutation<ExampleUpdateMutation, ExampleUpdateMutationVariables>(ExampleDocument);

useMutationAllTyped.mutate({ id: "2", example: { name: "remix" } }, {});

useMutationAllTyped.onDone(param => {
assertExactType<typeof param, FetchResult<ExampleUpdateMutation> | undefined>(param);
assertExactType<typeof param.data.exampleUpdate, ExampleUpdatePayload>(
param.data.exampleUpdate
);
});
}

// =============================================================================
// With all things typed and with options and variables
// - TResult should be the mutation type
Expand Down Expand Up @@ -170,7 +201,7 @@ import { assertExactType } from "./assertions";
}
);

assertExactType<typeof withVariablesInOptions.mutate, MutateWithOptionalVariables<ExampleUpdateMutation, ExampleUpdateMutationVariables>>(
assertExactType<typeof withVariablesInOptions.mutate, MutateFunction<ExampleUpdateMutation, ExampleUpdateMutationVariables>>(
withVariablesInOptions.mutate
)

Expand All @@ -193,7 +224,7 @@ import { assertExactType } from "./assertions";
ExampleDocument
);

assertExactType<typeof withNoOptions.mutate, MutateWithRequiredVariables<ExampleUpdateMutation, ExampleUpdateMutationVariables>>(
assertExactType<typeof withNoOptions.mutate, MutateFunction<ExampleUpdateMutation, ExampleUpdateMutationVariables>>(
withNoOptions.mutate
)

Expand Down Expand Up @@ -236,7 +267,7 @@ import { assertExactType } from "./assertions";
}
);

assertExactType<typeof withNoVariablesInOptions.mutate, MutateWithRequiredVariables<ExampleUpdateMutation, ExampleUpdateMutationVariables>>(
assertExactType<typeof withNoVariablesInOptions.mutate, MutateFunction<ExampleUpdateMutation, ExampleUpdateMutationVariables>>(
withNoVariablesInOptions.mutate
)

Expand Down
17 changes: 17 additions & 0 deletions packages/vue-apollo-composable/tests/types/useQuery-types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<ExampleQuery, ExampleQueryVariables>(ExampleDocument);

const useQueryAllTypedResult = useQueryAllTyped.result.value;
assertExactType<typeof useQueryAllTypedResult, ExampleQuery>(useQueryAllTypedResult);

const useQueryAllTypedVariables = useQueryAllTyped.variables.value;
assertExactType<typeof useQueryAllTypedVariables, ExampleQueryVariables>(
useQueryAllTypedVariables
);
}

// =============================================================================
// With query types, and no variables
// - TResult should be the query type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof useSubscription_AllTypedResult, ExampleUpdatedSubscription>(
useSubscription_AllTypedResult
);

// Variables type should match the passed in variables type
const useSubscription_AllTypedVariables = useSubscription_AllTyped.variables.value;
assertExactType<typeof useSubscription_AllTypedVariables, ExampleUpdatedSubscriptionVariables>(
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
Expand Down

0 comments on commit 7495987

Please sign in to comment.