From 2ddfb1ccb24c5fcabd2e03c72f30240b5320bdc0 Mon Sep 17 00:00:00 2001 From: unnoq <contact@unnoq.com> Date: Mon, 3 Mar 2025 10:21:25 +0700 Subject: [PATCH 1/3] feat(query-core): make `MutateFunction` optional undefinable-variables --- .../query-core/src/__tests__/types.test-d.tsx | 59 +++++++++++++++++++ packages/query-core/src/types.ts | 18 +++++- 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 packages/query-core/src/__tests__/types.test-d.tsx diff --git a/packages/query-core/src/__tests__/types.test-d.tsx b/packages/query-core/src/__tests__/types.test-d.tsx new file mode 100644 index 0000000000..0b0b4cd72d --- /dev/null +++ b/packages/query-core/src/__tests__/types.test-d.tsx @@ -0,0 +1,59 @@ +import { describe, expectTypeOf, it } from 'vitest' +import type { MutateFunction } from 'src/types' + +describe('MutateFunction', () => { + it('optional undefinable variables', () => { + const mutate = {} as MutateFunction< + unknown, + unknown, + number | undefined, + unknown + > + + expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf< + number | undefined + >() + + mutate() // can be called with no arguments + }) + + it('required non-undefinable variables', () => { + const mutate = {} as MutateFunction<unknown, unknown, number, unknown> + + expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf<number>() + + // @ts-expect-error --- required variables + mutate() + }) + + describe('compatible with spread arguments pattern', () => { + // this is common pattern used internal so we need make sure it still works + + it('optional undefinable variables', () => { + const mutate = {} as ( + ...options: Parameters< + MutateFunction<unknown, unknown, number | undefined, unknown> + > + ) => void + + expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf< + number | undefined + >() + + mutate() // can be called with no arguments + }) + + it('required non-undefinable variables', () => { + const mutate = {} as ( + ...options: Parameters< + MutateFunction<unknown, unknown, number, unknown> + > + ) => void + + expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf<number>() + + // @ts-expect-error --- required variables + mutate() + }) + }) +}) diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index 6d94daabc0..8e1c7bc8c8 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -1149,14 +1149,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< From 30858702fb524c8370b3013aed237f62b527fcc8 Mon Sep 17 00:00:00 2001 From: unnoq <contact@unnoq.com> Date: Tue, 4 Mar 2025 19:46:15 +0700 Subject: [PATCH 2/3] test(query-core): MutateFunction --- .../src/__tests__/mutation.test-d.tsx | 135 ++++++++++++++++++ .../query-core/src/__tests__/types.test-d.tsx | 59 -------- 2 files changed, 135 insertions(+), 59 deletions(-) create mode 100644 packages/query-core/src/__tests__/mutation.test-d.tsx delete mode 100644 packages/query-core/src/__tests__/types.test-d.tsx diff --git a/packages/query-core/src/__tests__/mutation.test-d.tsx b/packages/query-core/src/__tests__/mutation.test-d.tsx new file mode 100644 index 0000000000..f5f15afdfc --- /dev/null +++ b/packages/query-core/src/__tests__/mutation.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/__tests__/types.test-d.tsx b/packages/query-core/src/__tests__/types.test-d.tsx deleted file mode 100644 index 0b0b4cd72d..0000000000 --- a/packages/query-core/src/__tests__/types.test-d.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { describe, expectTypeOf, it } from 'vitest' -import type { MutateFunction } from 'src/types' - -describe('MutateFunction', () => { - it('optional undefinable variables', () => { - const mutate = {} as MutateFunction< - unknown, - unknown, - number | undefined, - unknown - > - - expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf< - number | undefined - >() - - mutate() // can be called with no arguments - }) - - it('required non-undefinable variables', () => { - const mutate = {} as MutateFunction<unknown, unknown, number, unknown> - - expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf<number>() - - // @ts-expect-error --- required variables - mutate() - }) - - describe('compatible with spread arguments pattern', () => { - // this is common pattern used internal so we need make sure it still works - - it('optional undefinable variables', () => { - const mutate = {} as ( - ...options: Parameters< - MutateFunction<unknown, unknown, number | undefined, unknown> - > - ) => void - - expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf< - number | undefined - >() - - mutate() // can be called with no arguments - }) - - it('required non-undefinable variables', () => { - const mutate = {} as ( - ...options: Parameters< - MutateFunction<unknown, unknown, number, unknown> - > - ) => void - - expectTypeOf<Parameters<typeof mutate>[0]>().toEqualTypeOf<number>() - - // @ts-expect-error --- required variables - mutate() - }) - }) -}) From 02db0f2cfbc00237951c7ad9b7f543d17bdb6101 Mon Sep 17 00:00:00 2001 From: unnoq <contact@unnoq.com> Date: Tue, 4 Mar 2025 19:52:07 +0700 Subject: [PATCH 3/3] test(query-core): MutateFunction --- .../src/__tests__/{mutation.test-d.tsx => mutations.test-d.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/query-core/src/__tests__/{mutation.test-d.tsx => mutations.test-d.tsx} (100%) diff --git a/packages/query-core/src/__tests__/mutation.test-d.tsx b/packages/query-core/src/__tests__/mutations.test-d.tsx similarity index 100% rename from packages/query-core/src/__tests__/mutation.test-d.tsx rename to packages/query-core/src/__tests__/mutations.test-d.tsx