news 2026/9/11 15:55:41

Svelte Query CreateQueryOptions 类型指南:createQuery 全部选项的 TypeScript 权威解读

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Svelte Query CreateQueryOptions 类型指南:createQuery 全部选项的 TypeScript 权威解读

Svelte Query CreateQueryOptions 类型指南:createQuery 全部选项的 TypeScript 权威解读

【免费下载链接】query🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query

CreateQueryOptions是 TanStack Svelte Query 中createQuery组合式函数(hook)的参数类型,它描述了如何声明一次数据请求的全部行为:从queryKeyqueryFn这类必填核心字段,到enabledstaleTimeretryselect等数十个用于控制缓存、重试、自动刷新与派生数据的可选配置。本文以该类型的源码定义为主体,完整解析其类型参数、继承链上的全部字段及其默认值与底层实现,帮助你写出类型安全、行为可控的 Svelte 数据获取代码。

一、类型定义:一行别名背后的继承链

CreateQueryOptions定义在 packages/svelte-query/src/types.ts 中,其完整声明如下:

/** Options for createQuery */ export type CreateQueryOptions< TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, > = CreateBaseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>

从源码结构看,这是一个层层转发的类型别名:

  • CreateQueryOptionsCreateBaseQueryOptions(定义于 packages/svelte-query/src/types.ts 第 24-31 行)
  • CreateBaseQueryOptionsQueryObserverOptions(来自@tanstack/query-core

CreateQueryOptions最终等价于QueryObserverOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>。注意其中TQueryData(观测器内部缓存的原始数据类型)被固定为TQueryFnData,这保证了select变换前的数据形态与查询函数返回的数据形态一致。

QueryObserverOptions定义于 packages/query-core/src/types.ts,它通过WithRequired<QueryOptions<...>, 'queryKey'>强制要求queryKey必填,并在此之上补充了观测器(observer)层面的行为选项。因此,CreateQueryOptions的字段空间 =QueryOptions的全部字段 +QueryObserverOptions的全部字段。

二、四个类型参数:从数据形态到错误类型的完整约束

原文档声明了 4 个泛型参数,理解它们之间的默认值联动关系是掌握该类型的关键:

类型参数约束默认值含义
TQueryFnDataunknownqueryFn返回的原始数据类型,即缓存中存储的数据类型
TErrorDefaultError查询失败时error的类型,默认是unknown的包装
TDataTQueryFnData组件实际读取到的数据类型;设置selectTData为选择器返回值
TQueryKeyextends QueryKeyQueryKey查询键类型,必须是QueryKeyreadonly unknown[])的子类型

关键联动逻辑:

  • 若不传TData,它默认等于TQueryFnData,因此普通查询的query.data类型就是queryFn的返回类型;
  • 一旦使用select: (data) => ...TData会被推断为选择器的返回类型(见下文实战示例);
  • TQueryKey默认是宽泛的QueryKey,但显式传入字面量类型(如['post', postId])可获得更精确的查询键类型推导,配合queryOptions还能让queryKey携带数据类型标签(QueryKeyWithDataTag)。

这四个参数贯穿整个 Svelte Query 的类型体系:CreateQueryResult<TData, TError>DefinedCreateQueryResult<TData, TError>等结果类型都与之对应,保证"选项类型 → 结果类型"的完全一致。

三、完整选项字段清单:全部配置项、默认值与作用

以下字段是CreateQueryOptions可接受的全部配置,分为两层列出(来源:packages/query-core/src/types.ts)。

3.1 QueryObserverOptions 层:控制组件观测行为

字段类型默认值作用
enabledboolean \| (query) => booleantrue设为false时挂载或查询键变化不会自动请求,需手动调用refetch
staleTimenumber \| (query) => number0数据被视为过期的时间(毫秒);Infinity表示永不过期
refetchIntervalnumber \| false \| (query) => number \| false \| undefinedfalse定时轮询频率(毫秒),函数形式可根据最新数据动态计算
refetchIntervalInBackgroundbooleanfalsetrue时标签页/窗口在后台也继续轮询
refetchOnWindowFocusboolean \| 'always' \| (query) => ...true窗口聚焦且数据过期时自动重新请求;'always'无条件刷新
refetchOnReconnectboolean \| 'always' \| (query) => ...truenetworkMode: 'always'时为false网络重连时自动重新请求
refetchOnMountboolean \| 'always' \| (query) => ...true组件挂载时若数据过期则刷新;false阻止同一查询的额外实例触发后台刷新
retryOnMountboolean \| (query) => booleantrue挂载时若查询曾失败是否再次重试
notifyOnChangePropsstring[] \| 'all' \| (() => string[])跟踪访问属性仅当列出的属性变化时触发组件重渲染;默认按访问追踪
throwOnErrorboolean \| (error, query) => booleanfalsetrue或配合suspense时把错误抛给错误边界,而不是放入error状态
select(data: TQueryData) => TData从缓存数据变换出组件需要的部分数据,不改变缓存内容
suspensebooleanfalsetruestatus === 'pending'挂起、status === 'error'抛错
placeholderDataTQueryData \| 函数initialData且数据加载中时显示的占位数据(如keepPreviousData
_optimisticResults'optimistic' \| 'isRestoring'内部使用的乐观结果标记

3.2 QueryOptions 层:查询本身的运行与缓存策略

字段类型默认值作用
queryKeyTQueryKey必填(无默认)查询的唯一标识,用于缓存命中与失效
queryFnQueryFunction \| SkipToken实际发起请求的函数;使用skipToken可跳过请求
retryboolean \| number \| (failureCount, error) => boolean3失败重试次数;true无限重试,false不重试
retryDelaynumber \| (retryAttempt, error) => number指数退避重试间隔(毫秒),默认按重试次数指数递增
networkMode'online' \| 'always' \| 'offlineFirst''online'控制网络不可用时的行为
gcTimenumber5 分钟(默认)缓存变为未使用/非活动后保留在内存的时间(毫秒),Infinity关闭垃圾回收
queryHashstring由键哈希生成查询哈希,用于内部定位查询
queryKeyHashFn(queryKey) => string默认哈希自定义查询键哈希函数
initialDataTData \| () => TData首次渲染即有的初始数据,可避免 loading 状态
initialDataUpdatedAtnumber \| () => number \| undefinedinitialData的时间戳,影响 stale 判断
structuralSharingboolean \| (oldData, newData) => unknowntrue结构共享,数据形状未变时复用旧引用避免多余重渲染
persisterQueryPersister自定义查询持久化器
behaviorQueryBehavior查询行为扩展
metaQueryMeta附加到查询上的任意负载,供其他地方读取
maxPagesnumber无限查询最大缓存页数

注意:以上默认值(如retry: 3gcTime: 5 分钟)为 Query 核心的常规默认,实际生效值还取决于QueryClient构造时的全局默认配置,二者会合并。

四、响应式 Accessor 包裹:Svelte 5 特有的选项声明方式

createQuery的选项参数被包装为Accessor<T>(即() => T),这是 Svelte Query 适配 Svelte 5 runes 响应式系统的核心设计。createQuery的最终实现(见 packages/svelte-query/src/createQuery.ts):

export function createQuery( options: Accessor<CreateQueryOptions>, queryClient?: Accessor<QueryClient>, ) { return createBaseQuery(options, QueryObserver, queryClient) }

这意味着在.svelte组件中,你需要把选项包在一个函数里,任何$state/$props的变化都会让选项重新求值:

<script lang="ts"> import { createQuery } from '@tanstack/svelte-query' let { postId }: { postId: number | undefined } = $props() const query = createQuery(() => ({ queryKey: ['post', postId], queryFn: () => fetchPost(postId!), enabled: postId != null, })) </script>

queryClient同样是可选的Accessor<QueryClient>,不传时使用最近上下文中的客户端。

五、initialData 重载:类型上消灭undefined

createQuery依据是否提供initialData选择了不同重载(packages/svelte-query/src/queryOptions.ts):

  • 未提供initialData时使用UndefinedInitialDataOptions,此时TQueryFnDataNonUndefinedGuard约束;
  • 提供initialData时使用DefinedInitialDataOptions,返回DefinedCreateQueryResult,其中data保证永不为undefinedstatus不会解析为pending(除非请求失败且保留旧数据)。
<script lang="ts"> import { createQuery } from '@tanstack/svelte-query' // data 是 Post[],绝不会是 undefined const query = createQuery(() => ({ queryKey: ['posts'], queryFn: fetchPosts, initialData: [], })) </script> {#if query.isError} <span>Error: {query.error.message}</span> {/if} <ul> {#each query.data as post (post.id)} <li>{post.title}</li> {/each} </ul>

六、queryOptions:把选项提升为可共享、可复用的一等公民

queryOptions接受与createQuery完全相同的选项对象,返回时给queryKey附加数据类型标签(QueryKeyWithDataTag),使选项既可用于组件内的createQuery,也可用于命令式 API(如queryClient.queryqueryClient.fetchQuery),实现一份定义多处消费:

<script lang="ts"> import { queryOptions, createQuery } from '@tanstack/svelte-query' const postOptions = (id: string) => queryOptions({ queryKey: ['post', id], queryFn: () => fetchPost(id), }) let { id }: { id: string } = $props() const query = createQuery(() => postOptions(id)) </script>

七、常用配置组合实战

结合 createQuery.ts 的文档示例 与上文字段,以下是几组高频组合。

7.1 select 派生数据而不污染缓存

<script lang="ts"> import { createQuery } from '@tanstack/svelte-query' // 缓存仍存完整 Post[],组件只读取数量 const query = createQuery(() => ({ queryKey: ['posts'], queryFn: fetchPosts, select: (posts) => posts.length, })) </script> {#if query.isPending} Loading... {:else if query.isError} <span>Error: {query.error.message}</span> {:else} <span>{query.data} posts</span> {/if}

7.2 initialData 从缓存播种详情页

<script lang="ts"> import { createQuery, useQueryClient } from '@tanstack/svelte-query' let { postId }: { postId: number } = $props() const queryClient = useQueryClient() const query = createQuery(() => ({ queryKey: ['post', postId], queryFn: () => fetchPost(postId), initialData: () => queryClient .getQueryData<Array<Post>>(['posts']) ?.find((post) => post.id === postId), })) </script>

7.3 分页时保留上一页数据

<script lang="ts"> import { createQuery, keepPreviousData } from '@tanstack/svelte-query' let page = $state(0) const query = createQuery(() => ({ queryKey: ['posts', page], queryFn: () => fetchPosts(page), placeholderData: keepPreviousData, })) </script> <button disabled={query.isPlaceholderData} onclick={() => page++}> Next Page </button>

7.4 依赖查询:enabled 与 isLoading 配合

依赖其他数据的查询应使用enabled关闭自动请求,并用isLoading(而非isPending)判断,避免禁用期间误显示加载态:

<script lang="ts"> import { createQuery } from '@tanstack/svelte-query' let { postId }: { postId: number | undefined } = $props() const query = createQuery(() => ({ queryKey: ['post', postId], queryFn: () => fetchPost(postId!), enabled: postId != null, })) </script> {#if postId == null} Select a post {:else if query.isLoading} Loading... {:else if query.isError} <span>Error: {query.error.message}</span> {:else} <h1>{query.data?.title}</h1> {/if}

八、关联类型一览

CreateQueryOptions不是孤立存在,它与 Svelte Query 类型体系中的以下成员紧密关联(均定义于 packages/svelte-query/src/types.ts):

  • CreateBaseQueryOptions:底层选项类型,比CreateQueryOptions多一个TQueryData参数,供内部createBaseQuery使用;
  • CreateQueryResult<TData, TError>createQuery的返回值类型;
  • DefinedCreateQueryResult:提供initialData时保证data非空的返回类型;
  • CreateInfiniteQueryOptionscreateInfiniteQuery的选项类型,额外包含initialPageParamgetNextPageParamgetPreviousPageParammaxPages
  • UndefinedInitialDataOptions/DefinedInitialDataOptionscreateQuery两个重载使用的细分选项类型。

理解CreateQueryOptions就等于掌握了 Svelte Query 声明式数据获取的全部旋钮:从数据形态(四个泛型参数)、请求时机(enabled/refetchOn*)、失败策略(retry/retryDelay/throwOnError)、缓存寿命(gcTime/staleTime/structuralSharing)到派生展示(select/placeholderData/initialData),均可在类型系统的保护下组合使用。

【免费下载链接】query🤖 Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 15:53:27

Flutter for OpenHarmony 实战:从环境配置到轮播组件深度定制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 15:52:53

OpenClaw界面汉化:Tampermonkey脚本精准中文化实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 15:50:39

WorkBuddy连接全攻略:服务、资源与记忆的深度整合

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 15:48:41

WorkBuddy开放平台Agent开发实战:Skill工具调用与授权配置全指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华