From 650b71d37003c055b01adde323587065404124bc Mon Sep 17 00:00:00 2001 From: Wonsuk Choi Date: Wed, 23 Sep 2026 19:17:18 +0900 Subject: [PATCH 1/3] fix(solid-query/{queryOptions,useQuery}): correct the overload selected for 'initialData' --- ...solid-queryoptions-initialdata-overload.md | 5 + .../src/__tests__/queryOptions.test-d.tsx | 9 ++ packages/solid-query/src/queryOptions.ts | 11 +- packages/solid-query/src/useQuery.ts | 104 +++++++++--------- 4 files changed, 75 insertions(+), 54 deletions(-) create mode 100644 .changeset/solid-queryoptions-initialdata-overload.md diff --git a/.changeset/solid-queryoptions-initialdata-overload.md b/.changeset/solid-queryoptions-initialdata-overload.md new file mode 100644 index 00000000000..4091a49dd70 --- /dev/null +++ b/.changeset/solid-queryoptions-initialdata-overload.md @@ -0,0 +1,5 @@ +--- +'@tanstack/solid-query': patch +--- + +fix(solid-query/{queryOptions,useQuery}): correct the overload selected for 'initialData' diff --git a/packages/solid-query/src/__tests__/queryOptions.test-d.tsx b/packages/solid-query/src/__tests__/queryOptions.test-d.tsx index 468c5e8d0a6..abc220f5bd4 100644 --- a/packages/solid-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/solid-query/src/__tests__/queryOptions.test-d.tsx @@ -103,6 +103,15 @@ describe('queryOptions', () => { expectTypeOf(tagged[dataTagSymbol]).toEqualTypeOf() }) + it('should tag the queryKey with the result type of the QueryFn when initialData may be undefined', () => { + const { queryKey: tagged } = queryOptions({ + queryKey: queryKey(), + queryFn: () => Promise.resolve(5), + initialData: Math.random() > 0.5 ? 5 : undefined, + }) + + expectTypeOf(tagged[dataTagSymbol]).toEqualTypeOf() + }) it('should tag the queryKey even if no promise is returned', () => { const { queryKey: tagged } = queryOptions({ queryKey: queryKey(), diff --git a/packages/solid-query/src/queryOptions.ts b/packages/solid-query/src/queryOptions.ts index 6b6eca2394b..aa1172acfd7 100644 --- a/packages/solid-query/src/queryOptions.ts +++ b/packages/solid-query/src/queryOptions.ts @@ -1,5 +1,7 @@ import type { DefaultError, + InitialDataFunction, + NonUndefinedGuard, QueryKey, QueryKeyWithDataTag, } from '@tanstack/query-core' @@ -24,7 +26,10 @@ export type UndefinedInitialDataOptions< TQueryKey extends QueryKey = QueryKey, > = Accessor< QueryOptions & { - initialData?: undefined + initialData?: + | undefined + | InitialDataFunction> + | NonUndefinedGuard } > @@ -44,7 +49,9 @@ export type DefinedInitialDataOptions< TQueryKey extends QueryKey = QueryKey, > = Accessor< QueryOptions & { - initialData: TQueryFnData | (() => TQueryFnData) + initialData: + | NonUndefinedGuard + | (() => NonUndefinedGuard) } > diff --git a/packages/solid-query/src/useQuery.ts b/packages/solid-query/src/useQuery.ts index 536b9160a33..0bd9d99dc7b 100644 --- a/packages/solid-query/src/useQuery.ts +++ b/packages/solid-query/src/useQuery.ts @@ -14,6 +14,58 @@ import type { UndefinedInitialDataOptions, } from './queryOptions' +/** + * Subscribes to a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. + * The query runs when the options call for it — `enabled: false` skips the initial fetch. + * + * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless + * a `select` changes `TData` to include `undefined`). + * + * @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`. + * @param options - An accessor returning the {@link DefinedInitialDataOptions} to use — everything you can + * pass to `useQuery`, with `initialData` set. + * @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context + * will be used. + * @returns The current query result, as a Solid store, typed so that `status` is `success` — or `error` if a + * fetch attempt fails while keeping the existing data (`status` never resolves to `pending` in this overload's + * type, since `initialData` guarantees data upfront). `isSuccess`/`isError` are derived booleans for + * convenience. + * + * @example + * ```tsx + * import { For } from 'solid-js' + * import { useQuery } from '@tanstack/solid-query' + * + * function Posts() { + * // `postsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + * // list stays visible alongside the error. + * const postsQuery = useQuery(() => ({ + * queryKey: ['posts'], + * queryFn: fetchPosts, + * initialData: [], + * })) + * + * return ( + *
+ * {postsQuery.isError ? Error: {postsQuery.error.message} : null} + *
    + * {(post) =>
  • {post.title}
  • }
    + *
+ *
+ * ) + * } + * ``` + */ +export function useQuery< + TQueryFnData = unknown, + TError = DefaultError, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +>( + options: DefinedInitialDataOptions, + queryClient?: () => QueryClient, +): DefinedUseQueryResult + /** * Subscribes to a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. * The query runs when the options call for it — `enabled: false` skips the initial fetch. @@ -191,58 +243,6 @@ export function useQuery< options: UndefinedInitialDataOptions, queryClient?: () => QueryClient, ): UseQueryResult - -/** - * Subscribes to a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. - * The query runs when the options call for it — `enabled: false` skips the initial fetch. - * - * This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless - * a `select` changes `TData` to include `undefined`). - * - * @see {@link queryOptions} to share these options between `useQuery` and imperative APIs like `queryClient.query`. - * @param options - An accessor returning the {@link DefinedInitialDataOptions} to use — everything you can - * pass to `useQuery`, with `initialData` set. - * @param queryClient - An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context - * will be used. - * @returns The current query result, as a Solid store, typed so that `status` is `success` — or `error` if a - * fetch attempt fails while keeping the existing data (`status` never resolves to `pending` in this overload's - * type, since `initialData` guarantees data upfront). `isSuccess`/`isError` are derived booleans for - * convenience. - * - * @example - * ```tsx - * import { For } from 'solid-js' - * import { useQuery } from '@tanstack/solid-query' - * - * function Posts() { - * // `postsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - * // list stays visible alongside the error. - * const postsQuery = useQuery(() => ({ - * queryKey: ['posts'], - * queryFn: fetchPosts, - * initialData: [], - * })) - * - * return ( - *
- * {postsQuery.isError ? Error: {postsQuery.error.message} : null} - *
    - * {(post) =>
  • {post.title}
  • }
    - *
- *
- * ) - * } - * ``` - */ -export function useQuery< - TQueryFnData = unknown, - TError = DefaultError, - TData = TQueryFnData, - TQueryKey extends QueryKey = QueryKey, ->( - options: DefinedInitialDataOptions, - queryClient?: () => QueryClient, -): DefinedUseQueryResult export function useQuery< TQueryFnData, TError = DefaultError, From 4631f83efe3c05d1bd13bdb6a397a81b9c355efd Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 25 Sep 2026 07:26:03 +0000 Subject: [PATCH 2/3] ci: apply automated fixes --- packages/solid-query/src/queryOptions.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/solid-query/src/queryOptions.ts b/packages/solid-query/src/queryOptions.ts index aa1172acfd7..ffe69506045 100644 --- a/packages/solid-query/src/queryOptions.ts +++ b/packages/solid-query/src/queryOptions.ts @@ -50,8 +50,7 @@ export type DefinedInitialDataOptions< > = Accessor< QueryOptions & { initialData: - | NonUndefinedGuard - | (() => NonUndefinedGuard) + NonUndefinedGuard | (() => NonUndefinedGuard) } > From 530342f2f27e992f579d3a9f387752d470822caf Mon Sep 17 00:00:00 2001 From: Wonsuk Choi Date: Mon, 5 Oct 2026 04:15:01 +0900 Subject: [PATCH 3/3] docs(framework/*/reference): regenerate reference docs --- .../solid/reference/functions/queryOptions.md | 4 +- .../solid/reference/functions/useQuery.md | 176 +++++++++--------- .../type-aliases/DefinedInitialDataOptions.md | 2 +- .../UndefinedInitialDataOptions.md | 2 +- .../solid/reference/variables/createQuery.md | 172 ++++++++--------- 5 files changed, 178 insertions(+), 178 deletions(-) diff --git a/docs/framework/solid/reference/functions/queryOptions.md b/docs/framework/solid/reference/functions/queryOptions.md index 618f50a2e42..51758af968e 100644 --- a/docs/framework/solid/reference/functions/queryOptions.md +++ b/docs/framework/solid/reference/functions/queryOptions.md @@ -11,7 +11,7 @@ redirect_from: function queryOptions(options: QueryOptions & object): QueryOptions & object & QueryKeyWithDataTag; ``` -Defined in: [packages/solid-query/src/queryOptions.ts:86](https://github.com/TanStack/query/blob/main/packages/solid-query/src/queryOptions.ts#L86) +Defined in: [packages/solid-query/src/queryOptions.ts:92](https://github.com/TanStack/query/blob/main/packages/solid-query/src/queryOptions.ts#L92) You can generally pass everything to `queryOptions` that you can also pass to `useQuery`. These options can be shared across hooks and imperative APIs such as `queryClient.query`. `options.queryKey` is required and @@ -90,7 +90,7 @@ function Posts() { function queryOptions(options: QueryOptions & object): QueryOptions & object & QueryKeyWithDataTag; ``` -Defined in: [packages/solid-query/src/queryOptions.ts:134](https://github.com/TanStack/query/blob/main/packages/solid-query/src/queryOptions.ts#L134) +Defined in: [packages/solid-query/src/queryOptions.ts:140](https://github.com/TanStack/query/blob/main/packages/solid-query/src/queryOptions.ts#L140) You can generally pass everything to `queryOptions` that you can also pass to `useQuery`. These options can be shared across hooks and imperative APIs such as `queryClient.query`. `options.queryKey` is required and diff --git a/docs/framework/solid/reference/functions/useQuery.md b/docs/framework/solid/reference/functions/useQuery.md index 87f4f313b6d..c87dce193cf 100644 --- a/docs/framework/solid/reference/functions/useQuery.md +++ b/docs/framework/solid/reference/functions/useQuery.md @@ -7,11 +7,98 @@ redirect_from: ## Call Signature +```ts +function useQuery(options: DefinedInitialDataOptions, queryClient?: () => QueryClient): DefinedUseQueryResult; +``` + +Defined in: [packages/solid-query/src/useQuery.ts:57](https://github.com/TanStack/query/blob/main/packages/solid-query/src/useQuery.ts#L57) + +Subscribes to a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. +The query runs when the options call for it — `enabled: false` skips the initial fetch. + +This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless +a `select` changes `TData` to include `undefined`). + +### Type Parameters + +#### TQueryFnData + +`TQueryFnData` = `unknown` + +#### TError + +`TError` = `Error` + +#### TData + +`TData` = `TQueryFnData` + +#### TQueryKey + +`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[] + +### Parameters + +#### options + +[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> + +An accessor returning the [DefinedInitialDataOptions](../type-aliases/DefinedInitialDataOptions.md) to use — everything you can +pass to `useQuery`, with `initialData` set. + +#### queryClient? + +() => [`QueryClient`](../classes/QueryClient.md) + +An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context +will be used. + +### Returns + +[`DefinedUseQueryResult`](../type-aliases/DefinedUseQueryResult.md)\<`TData`, `TError`\> + +The current query result, as a Solid store, typed so that `status` is `success` — or `error` if a +fetch attempt fails while keeping the existing data (`status` never resolves to `pending` in this overload's +type, since `initialData` guarantees data upfront). `isSuccess`/`isError` are derived booleans for +convenience. + +### See + +[queryOptions](queryOptions.md) to share these options between `useQuery` and imperative APIs like `queryClient.query`. + +### Example + +```tsx +import { For } from 'solid-js' +import { useQuery } from '@tanstack/solid-query' + +function Posts() { + // `postsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + // list stays visible alongside the error. + const postsQuery = useQuery(() => ({ + queryKey: ['posts'], + queryFn: fetchPosts, + initialData: [], + })) + + return ( +
+ {postsQuery.isError ? Error: {postsQuery.error.message} : null} +
    + {(post) =>
  • {post.title}
  • }
    +
+
+ ) +} +``` + +## Call Signature + ```ts function useQuery(options: UndefinedInitialDataOptions, queryClient?: () => QueryClient): UseQueryResult; ``` -Defined in: [packages/solid-query/src/useQuery.ts:178](https://github.com/TanStack/query/blob/main/packages/solid-query/src/useQuery.ts#L178) +Defined in: [packages/solid-query/src/useQuery.ts:228](https://github.com/TanStack/query/blob/main/packages/solid-query/src/useQuery.ts#L228) Subscribes to a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. The query runs when the options call for it — `enabled: false` skips the initial fetch. @@ -212,90 +299,3 @@ function Posts() { ) } ``` - -## Call Signature - -```ts -function useQuery(options: DefinedInitialDataOptions, queryClient?: () => QueryClient): DefinedUseQueryResult; -``` - -Defined in: [packages/solid-query/src/useQuery.ts:228](https://github.com/TanStack/query/blob/main/packages/solid-query/src/useQuery.ts#L228) - -Subscribes to a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. -The query runs when the options call for it — `enabled: false` skips the initial fetch. - -This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless -a `select` changes `TData` to include `undefined`). - -### Type Parameters - -#### TQueryFnData - -`TQueryFnData` = `unknown` - -#### TError - -`TError` = `Error` - -#### TData - -`TData` = `TQueryFnData` - -#### TQueryKey - -`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[] - -### Parameters - -#### options - -[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> - -An accessor returning the [DefinedInitialDataOptions](../type-aliases/DefinedInitialDataOptions.md) to use — everything you can -pass to `useQuery`, with `initialData` set. - -#### queryClient? - -() => [`QueryClient`](../classes/QueryClient.md) - -An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context -will be used. - -### Returns - -[`DefinedUseQueryResult`](../type-aliases/DefinedUseQueryResult.md)\<`TData`, `TError`\> - -The current query result, as a Solid store, typed so that `status` is `success` — or `error` if a -fetch attempt fails while keeping the existing data (`status` never resolves to `pending` in this overload's -type, since `initialData` guarantees data upfront). `isSuccess`/`isError` are derived booleans for -convenience. - -### See - -[queryOptions](queryOptions.md) to share these options between `useQuery` and imperative APIs like `queryClient.query`. - -### Example - -```tsx -import { For } from 'solid-js' -import { useQuery } from '@tanstack/solid-query' - -function Posts() { - // `postsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - // list stays visible alongside the error. - const postsQuery = useQuery(() => ({ - queryKey: ['posts'], - queryFn: fetchPosts, - initialData: [], - })) - - return ( -
- {postsQuery.isError ? Error: {postsQuery.error.message} : null} -
    - {(post) =>
  • {post.title}
  • }
    -
-
- ) -} -``` diff --git a/docs/framework/solid/reference/type-aliases/DefinedInitialDataOptions.md b/docs/framework/solid/reference/type-aliases/DefinedInitialDataOptions.md index e24fb30e1cc..d2b4a397f06 100644 --- a/docs/framework/solid/reference/type-aliases/DefinedInitialDataOptions.md +++ b/docs/framework/solid/reference/type-aliases/DefinedInitialDataOptions.md @@ -7,7 +7,7 @@ title: DefinedInitialDataOptions type DefinedInitialDataOptions = Accessor & object>; ``` -Defined in: [packages/solid-query/src/queryOptions.ts:38](https://github.com/TanStack/query/blob/main/packages/solid-query/src/queryOptions.ts#L38) +Defined in: [packages/solid-query/src/queryOptions.ts:43](https://github.com/TanStack/query/blob/main/packages/solid-query/src/queryOptions.ts#L43) The options accepted by the `queryOptions` overload selected when `initialData` is set — `data` is never `undefined` (unless a `select` changes `TData` to include `undefined`). diff --git a/docs/framework/solid/reference/type-aliases/UndefinedInitialDataOptions.md b/docs/framework/solid/reference/type-aliases/UndefinedInitialDataOptions.md index da188494059..625700ee933 100644 --- a/docs/framework/solid/reference/type-aliases/UndefinedInitialDataOptions.md +++ b/docs/framework/solid/reference/type-aliases/UndefinedInitialDataOptions.md @@ -7,7 +7,7 @@ title: UndefinedInitialDataOptions type UndefinedInitialDataOptions = Accessor & object>; ``` -Defined in: [packages/solid-query/src/queryOptions.ts:19](https://github.com/TanStack/query/blob/main/packages/solid-query/src/queryOptions.ts#L19) +Defined in: [packages/solid-query/src/queryOptions.ts:21](https://github.com/TanStack/query/blob/main/packages/solid-query/src/queryOptions.ts#L21) The options accepted by the `queryOptions` overload selected when no `initialData` is set — `data` may be `undefined` while the query is `pending`. `queryOptions` itself accepts and returns a plain object (its diff --git a/docs/framework/solid/reference/variables/createQuery.md b/docs/framework/solid/reference/variables/createQuery.md index 1d6e2be2b1b..7da4caac599 100644 --- a/docs/framework/solid/reference/variables/createQuery.md +++ b/docs/framework/solid/reference/variables/createQuery.md @@ -5,8 +5,8 @@ title: createQuery ```ts const createQuery: { - (options: UndefinedInitialDataOptions, queryClient?: () => QueryClient): UseQueryResult; (options: DefinedInitialDataOptions, queryClient?: () => QueryClient): DefinedUseQueryResult; + (options: UndefinedInitialDataOptions, queryClient?: () => QueryClient): UseQueryResult; } = useQuery; ``` @@ -14,6 +14,91 @@ Defined in: [packages/solid-query/src/index.ts:57](https://github.com/TanStack/q ## Call Signature +```ts +(options: DefinedInitialDataOptions, queryClient?: () => QueryClient): DefinedUseQueryResult; +``` + +Subscribes to a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. +The query runs when the options call for it — `enabled: false` skips the initial fetch. + +This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless +a `select` changes `TData` to include `undefined`). + +### Type Parameters + +#### TQueryFnData + +`TQueryFnData` = `unknown` + +#### TError + +`TError` = `Error` + +#### TData + +`TData` = `TQueryFnData` + +#### TQueryKey + +`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[] + +### Parameters + +#### options + +[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> + +An accessor returning the [DefinedInitialDataOptions](../type-aliases/DefinedInitialDataOptions.md) to use — everything you can +pass to `useQuery`, with `initialData` set. + +#### queryClient? + +() => [`QueryClient`](../classes/QueryClient.md) + +An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context +will be used. + +### Returns + +[`DefinedUseQueryResult`](../type-aliases/DefinedUseQueryResult.md)\<`TData`, `TError`\> + +The current query result, as a Solid store, typed so that `status` is `success` — or `error` if a +fetch attempt fails while keeping the existing data (`status` never resolves to `pending` in this overload's +type, since `initialData` guarantees data upfront). `isSuccess`/`isError` are derived booleans for +convenience. + +### See + +[queryOptions](../functions/queryOptions.md) to share these options between `useQuery` and imperative APIs like `queryClient.query`. + +### Example + +```tsx +import { For } from 'solid-js' +import { useQuery } from '@tanstack/solid-query' + +function Posts() { + // `postsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the + // list stays visible alongside the error. + const postsQuery = useQuery(() => ({ + queryKey: ['posts'], + queryFn: fetchPosts, + initialData: [], + })) + + return ( +
+ {postsQuery.isError ? Error: {postsQuery.error.message} : null} +
    + {(post) =>
  • {post.title}
  • }
    +
+
+ ) +} +``` + +## Call Signature + ```ts (options: UndefinedInitialDataOptions, queryClient?: () => QueryClient): UseQueryResult; ``` @@ -217,88 +302,3 @@ function Posts() { ) } ``` - -## Call Signature - -```ts -(options: DefinedInitialDataOptions, queryClient?: () => QueryClient): DefinedUseQueryResult; -``` - -Subscribes to a query: a declarative dependency on an asynchronous source of data that is tied to a unique key. -The query runs when the options call for it — `enabled: false` skips the initial fetch. - -This overload is selected when `initialData` is set, so the resulting `data` is never `undefined` (unless -a `select` changes `TData` to include `undefined`). - -### Type Parameters - -#### TQueryFnData - -`TQueryFnData` = `unknown` - -#### TError - -`TError` = `Error` - -#### TData - -`TData` = `TQueryFnData` - -#### TQueryKey - -`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[] - -### Parameters - -#### options - -[`DefinedInitialDataOptions`](../type-aliases/DefinedInitialDataOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\> - -An accessor returning the [DefinedInitialDataOptions](../type-aliases/DefinedInitialDataOptions.md) to use — everything you can -pass to `useQuery`, with `initialData` set. - -#### queryClient? - -() => [`QueryClient`](../classes/QueryClient.md) - -An accessor for a custom `QueryClient`. Otherwise, the one from the nearest context -will be used. - -### Returns - -[`DefinedUseQueryResult`](../type-aliases/DefinedUseQueryResult.md)\<`TData`, `TError`\> - -The current query result, as a Solid store, typed so that `status` is `success` — or `error` if a -fetch attempt fails while keeping the existing data (`status` never resolves to `pending` in this overload's -type, since `initialData` guarantees data upfront). `isSuccess`/`isError` are derived booleans for -convenience. - -### See - -[queryOptions](../functions/queryOptions.md) to share these options between `useQuery` and imperative APIs like `queryClient.query`. - -### Example - -```tsx -import { For } from 'solid-js' -import { useQuery } from '@tanstack/solid-query' - -function Posts() { - // `postsQuery.data` is never `undefined`, thanks to `initialData` — even if a refetch fails, so the - // list stays visible alongside the error. - const postsQuery = useQuery(() => ({ - queryKey: ['posts'], - queryFn: fetchPosts, - initialData: [], - })) - - return ( -
- {postsQuery.isError ? Error: {postsQuery.error.message} : null} -
    - {(post) =>
  • {post.title}
  • }
    -
-
- ) -} -```