diff --git a/packages/query-core/src/__tests__/mutations.test-d.tsx b/packages/query-core/src/__tests__/mutations.test-d.tsx
new file mode 100644
index 0000000000..f5f15afdfc
--- /dev/null
+++ b/packages/query-core/src/__tests__/mutations.test-d.tsx
@@ -0,0 +1,135 @@
+import { describe, expectTypeOf, it } from 'vitest'
+import type { DefaultError, MutateFunction, MutateOptions } from 'src/types'
+
+describe('MutateFunction', () => {
+  it('void variables', () => {
+    const mutate = {} as MutateFunction
+
+    expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf<
+      undefined | void
+    >()
+
+    expectTypeOf<Parameters<typeof mutate>[1]>().toEqualTypeOf<
+      undefined | MutateOptions<unknown, DefaultError, void, unknown>
+    >()
+
+    mutate() // can be called with no arguments
+    mutate(undefined, {
+      onError: (e) => {
+        expectTypeOf(e).toEqualTypeOf<DefaultError>()
+      },
+    })
+  })
+
+  it('optional undefinable variables', () => {
+    const mutate = {} as MutateFunction<
+      unknown,
+      DefaultError,
+      number | undefined,
+      unknown
+    >
+
+    expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf<
+      number | undefined
+    >()
+
+    expectTypeOf<Parameters<typeof mutate>[1]>().toEqualTypeOf<
+      | undefined
+      | MutateOptions<unknown, DefaultError, number | undefined, unknown>
+    >()
+
+    mutate() // can be called with no arguments
+    mutate(undefined, {
+      onError: (e) => {
+        expectTypeOf(e).toEqualTypeOf<DefaultError>()
+      },
+    })
+  })
+
+  it('required non-undefinable variables', () => {
+    const mutate = {} as MutateFunction<unknown, DefaultError, number, unknown>
+
+    expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf<number>()
+
+    expectTypeOf<Parameters<typeof mutate>[1]>().toEqualTypeOf<
+      undefined | MutateOptions<unknown, DefaultError, number, unknown>
+    >()
+
+    // @ts-expect-error --- required variables
+    mutate()
+    mutate(123, {
+      onError: (e) => {
+        expectTypeOf(e).toEqualTypeOf<DefaultError>()
+      },
+    })
+  })
+
+  describe('compatible with spread arguments pattern', () => {
+    // this is common pattern used internal so we need make sure it still works
+
+    it('void variables', () => {
+      const mutate = {} as (...options: Parameters<MutateFunction>) => void
+
+      expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf<
+        undefined | void
+      >()
+
+      expectTypeOf<Parameters<typeof mutate>[1]>().toEqualTypeOf<
+        undefined | MutateOptions<unknown, DefaultError, void, unknown>
+      >()
+
+      mutate() // can be called with no arguments
+      mutate(undefined, {
+        onError: (e) => {
+          expectTypeOf(e).toEqualTypeOf<DefaultError>()
+        },
+      })
+    })
+
+    it('optional undefinable variables', () => {
+      const mutate = {} as (
+        ...options: Parameters<
+          MutateFunction<unknown, DefaultError, number | undefined, unknown>
+        >
+      ) => void
+
+      expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf<
+        number | undefined
+      >()
+
+      expectTypeOf<Parameters<typeof mutate>[1]>().toEqualTypeOf<
+        | undefined
+        | MutateOptions<unknown, DefaultError, number | undefined, unknown>
+      >()
+
+      mutate() // can be called with no arguments
+      mutate(undefined, {
+        onError: (e) => {
+          expectTypeOf(e).toEqualTypeOf<DefaultError>()
+        },
+      })
+    })
+
+    it('required non-undefinable variables', () => {
+      const mutate = {} as (
+        ...options: Parameters<
+          MutateFunction<unknown, DefaultError, number, unknown>
+        >
+      ) => void
+
+      expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf<number>()
+
+      expectTypeOf<Parameters<typeof mutate>[1]>().toEqualTypeOf<
+        undefined | MutateOptions<unknown, DefaultError, number, unknown>
+      >()
+
+      // @ts-expect-error --- required variables
+      mutate()
+      mutate(123, {
+        onError: (e) => {
+          expectTypeOf(e).toEqualTypeOf<DefaultError>()
+        },
+      })
+    })
+  })
+})
diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts
index c973b6a758..c15419cad4 100644
--- a/packages/query-core/src/types.ts
+++ b/packages/query-core/src/types.ts
@@ -1161,14 +1161,28 @@ export interface MutateOptions<
   ) => void
 }
 
+export type MutateFunctionRest<
+  TData = unknown,
+  TError = DefaultError,
+  TVariables = void,
+  TContext = unknown,
+> = undefined extends TVariables
+  ? [
+      variables?: TVariables,
+      options?: MutateOptions<TData, TError, TVariables, TContext>,
+    ]
+  : [
+      variables: TVariables,
+      options?: MutateOptions<TData, TError, TVariables, TContext>,
+    ]
+
 export type MutateFunction<
   TData = unknown,
   TError = DefaultError,
   TVariables = void,
   TContext = unknown,
 > = (
-  variables: TVariables,
-  options?: MutateOptions<TData, TError, TVariables, TContext>,
+  ...rest: MutateFunctionRest<TData, TError, TVariables, TContext>
 ) => Promise<TData>
 
 export interface MutationObserverBaseResult<