lukemorales / query-key-factory

A library for creating typesafe standardized query keys, useful for cache management in @tanstack/query
https://www.npmjs.com/package/@lukemorales/query-key-factory
MIT License
1.16k stars 32 forks source link

New createMutationKeys doesn't work for mutations with arguments #55

Open brmenchl opened 1 year ago

brmenchl commented 1 year ago

I first tried to follow the standard practice like for parametrized queries

export const todos = createMutationKeys('todos', {
  prop: (input: string) => ({
    mutationKey: [input],
    mutationFn: () => Promise.resolve(input),
  }),
});

...
const {mutate} = useMutation(todos.prop('hello');
// mutate has type UseMutateFunction<string, unknown, undefined, unknown>
mutate() // fails - arguments not provided (expected undefined)
mutate(undefined) // ok, returns void instead of Promise<string>

I also tried

export const todos = createMutationKeys('todos', {
  prop: {
    mutationKey: null,
    mutationFn: (input: string) => Promise.resolve(input),
  },
});

...
const {mutate} = useMutation(todos.prop);
// mutate has type UseMutateFunction<unknown, unknown, void, unknown>
mutate('hello') // fails - string is not assignable to 'void'
mutate() // ok, returns void instead of Promise<string> (but we haven't passed in the input string anywhere)

Neither gives me a workable type where I can pass in an argument. I could try to work on it myself but I'm not super familiar with this library yet.

jetaggart commented 1 year ago

I'm having this issue as well. I'm using this with graphql like so:

export const checkoutMutations = createMutationKeys("checkout", {
  create: {
    mutationKey: ["create"],
    mutationFn: (items: string[]) => {
      return request(CREATE_CHECKOUT, {input: {items}})
    }
  }
})

When I try to use this like this:

const createCheckout = useMutation(checkoutMutations.create)

That works fine but when I call it later, I get an error:

const result = await createCheckout.mutateAsync(cart.items.map(item => item.url))
=> TS2345: Argument of type 'string[]' is not assignable to parameter of type 'void'.
brmenchl commented 1 year ago

It looks like it has to do with the default type arguments in MutateFunction. Changing them to any fixes most usecases, except for when you want void as the arguments.

lukemorales commented 1 year ago

@jetaggart and @brmenchl thanks for bringing more context to the issue! I'll take a look on how to fix this

gusarizona commented 1 year ago

I am not sure if this is the problem (or at least a problem), but I noticed that createMutationKeys converts the properties mutationFn to type MutateFunction instead of MutationFunction. The hook useMutation expects MutationFunction not MutateFunction (the latter is actually the type for the mutate function returned by useMutation).

vohuynh19 commented 1 year ago

Any updates on this problem?

Fgruntjes commented 1 year ago

Not sure about react (using svelte) but you can just pass the types with the createMutation (svelte equivalent of useMutation) function.

const institutionConnectionMutation = createMutationKeys('InstitutionConnectionMutation', {
    create: () => ({
        mutationKey: ['create'],
        mutationFn: (request: InstitutionConnectionCreateRequest) => service.create(request),
    }),
})

const mutation = createMutation<
    InstitutionConnection,
    Error,
    InstitutionConnectionCreateRequest,
    unknown
>({
    ...institutionConnectionMutation.create()
});