React-query: Typescript - useMutation variables can't handle unions

Created on 7 Jul 2020  路  4Comments  路  Source: tannerlinsley/react-query

async function mutationFn(variables: { a: string } | { b: string }) {
    return true;
}

const useFoo = () => {
    const [mutate] = useMutation(mutationFn);
    mutate({ a: "" });
};

The code above produces this Typescript error:
Argument of type '{ a: string; }' is not assignable to parameter of type '{ a: string; } & { b: string; }'. Property 'b' is missing in type '{ a: string; }' but required in type '{ b: string; }'.

I have no idea why the expected type becomes the intersection { a: string; } & { b: string; } rather than the union I specified.

The type definition for MutateFunction is:

export type MutateFunction<
  TResult,
  TVariables,
  TError = Error
> = TVariables extends undefined
  ? (options?: MutateOptions<TResult, TVariables, TError>) => Promise<TResult>
  : (
      variables: TVariables,
      options?: MutateOptions<TResult, TVariables, TError>
    ) => Promise<TResult>

changing TVariables extends undefined to [TVariables] extends [undefined] seems to fix the problem. I don't understand why though.

I'm using version 2.4.13

Most helpful comment

Seems to be working correctly now when using the example in the React Query tests

All 4 comments

I bumped into the same issue. And it is a feature of typescript which is called Distributive conditional types.

With current implementation it means that for mutation function with string | number we will get union type of function (string) => Promise<TResult> | (number) => Promise<TResult> which will fail compilation. Expected type should be (string | number) => Promise<TResult>.

And wrapping conditional type into 1-tuple (convert TVariables extends undefined to [TVariables] extends [undefined] as you mentioned @Bene8493) works because type is not naked anymore. And it is a common way to avoid type distribution.

I'd be happy to raise a PR with this change, but if I get contribution guide correctly I should be assigned to this issue first, or...?

Thanks for looking into it. There's an open pull request to completely move the project to typescript. Might be worth waiting for that. #767

Is this still a valid problem now #767 is merged? 馃

Seems to be working correctly now when using the example in the React Query tests

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lgenzelis picture lgenzelis  路  4Comments

CreativeTechGuy picture CreativeTechGuy  路  3Comments

michaeljota picture michaeljota  路  6Comments

oukayuka picture oukayuka  路  4Comments

jackmellis picture jackmellis  路  5Comments