[edit] I've created a very simplified example of what my problem is: https://codesandbox.io/s/example-type-inference-for-generic-types-qyqz1?file=/src/index.ts
So I'm trying to make a wrapper that accepts the form-handler
and mutation
(generated with graphql-let
), to return a function that can be used in a form.
This is the code, but it throws an error on the variables
in mutation({ variables: {...})
(see below).
Type '{ input: UnpackNestedValue; }' is not assignable to type 'TVariables'. 'TVariables' could be instantiated with an arbitrary type which could be unrelated to '{ input: UnpackNestedValue; }'.ts(2322)
types.d.ts(92, 5): The expected type comes from property 'variables' which is declared here on type 'MutationFunctionOptions<TData, TVariables>'
I understand that TVariables
and TData
can be different, but TVariables
has default of OperationVariables
which is type { [key: string]: any }
, which is pretty generic.
How to solve this?
import {
FetchResult,
MutationFunctionOptions,
OperationVariables,
} from '@apollo/client';
import { UseFormHandleSubmit } from 'react-hook-form';
export const submitHandlerMutationFactory = <
TForm,
TData,
TVariables = OperationVariables
>(
submitHandler: UseFormHandleSubmit<TForm>,
mutation: (
options?: MutationFunctionOptions<TData, TVariables>
) => Promise<FetchResult<TData>>
) => {
return submitHandler((data) => mutation({ variables: { input: data } }));
};
EDIT after Kiuhnm's answer
It doesn't give the error anymore, but now I'm also missing the goal: getting the function to make sure the Types of the submitHandler
and the mutation
are the same.
However, if I use this, we get problems with the input
variable, similar to previous problem, but it DOES give me information over when calling the the function with two not-matching types.
export const submitHandlerMutationFactory = <TFormInputs, TMutation>(
submitHandler: UseFormHandleSubmit<TFormInputs>,
mutation: Apollo.MutationTuple<TMutation, { input: TFormInputs }>[0]
) => {
return submitHandler((data) => mutation({ variables: { input: data } }));
// Type 'UnpackNestedValue<TFormInputs>' is not assignable to type 'TFormInputs'.
// 'TFormInputs' could be instantiated with an arbitrary type which could be
// unrelated to 'UnpackNestedValue<TFormInputs>'.ts(2322)
};
const {
register,
handleSubmit,
watch,
formState: { errors },
} = useForm<LoginFormInputs>();
const [loginMutation, { data, loading, error }] = useLoginMutation();
type LoginFormInputs = {
username: string;
SOMETHING: string; // see explicit error below
};
const formSubmitHandler = submitHandlerMutationFactory(
handleSubmit,
loginMutation
// Property 'password' is missing in type 'LoginFormInputs' but required in type 'LoginInput'
);