Branded queryKey in queryOptions causes TS error (TS2769) in useQuery
メンテナーはふだん 1 日以内に返信
@byungsker がすでに取り組んでいます。
2026年4月25日 から。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 48/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 静か
- 技術スタック
- typescript
- 領域
- frontend
調査の方向性
リンクされているCodeSandboxとそのsrc/Post.vueの再現コードから始め、次にVueアダプターでqueryOptionsとuseQueryが使用するTypeScriptのオーバーロードを追跡します。branded queryKeyヘルパーがTS2769なしでコンパイルできることを確認し、動作しているfetchQueryとinline useQueryのケースを維持してください。
索引モデルが issue の本文から書いたものです。
説明
Describe the bug
I’m encountering a TypeScript overload mismatch (TS2769) when calling useQuery() with the result of a queryOptions(...) function whose returned object contains a queryKey with a branded type. The error occurs specifically when useQuery() receives the output of queryOptions(...) containing a branded value in queryKey.
Passing the same options to queryClient.fetchQuery(queryOptions(queryKey: brandedKey, queryFn)) — works fine.
Passing the branded key inline to useQuery (i.e. useQuery({ queryKey: brandedKey, queryFn})) — works fine.
Your minimal, reproducible example
https://codesandbox.io/p/devbox/tanstack-query-ts-error-2769-forked-spc8jh?file=%2Fsrc%2FPost.vue
Steps to reproduce
1. Define a branded type in your code:
type PostId = string & { readonly __brand: "PostId" };
2. Create a helper function that returns queryOptions where the queryKey includes a value using this branded type:
const getPostQueryOptions = (
params: MaybeRefOrGetter<{ postId: PostId }>
) => {
return queryOptions({
queryKey: ["post", params],
queryFn: () => fetcher(toValue(params).postId),
});
};
3. Call useQuery() using the result of this helper:
useQuery(getPostQueryOptions({ postId }));
4. Observe the TypeScript error:
No overload matches this call.
Overload 1 of 3, '(options: DefinedInitialQueryOptions<Post, Error, Post, MaybeRefDeep<string | (() => { postId: PostId; }) | { postId: PostId; }>[]>, queryClient?: QueryClient | undefined): UseQueryDefinedReturnType<...>', gave the following error.... ts(2769)
Expected behavior
useQuery() should correctly accept a QueryOptions object whose queryKey contains a branded (nominal) type.
In other words:
Passing the result of queryOptions(...) or any helper function that returns a QueryOptions object should not trigger a TypeScript overload error, even if the queryKey includes branded values.
How often does this bug happen?
Every time
Screenshots or Videos
Platform
- OS [Windows]
- Browser [Chrome]
Tanstack Query adapter
vue-query
TanStack Query version
v5.85.3
TypeScript version
v5.9.2
Additional context
No response
- 主要言語
- TypeScript
- スター
- 50.4k
- フォーク
- 4.2k
- 平均マージ
- 6時間 55分
- マージ済み PR(30日)
- 390
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
TanStack/query のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
TanStack/query#11930 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
solid-query: STRICT_READ_UNTRACKED on Solid 2 — client()/options() read in component body (useMutation, useBaseQuery)再び着手できるかも @LeonxLJX が 35 日前に担当しましたが、オープン中のプルリクエストはありません。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
TanStack/query#11358 · コメント 2 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
solid-query: switching the queryClient accessor strands the new client's cache (subscription stays on the old observer)対応中かも @MaNaN1803 が 78 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
TanStack/query#11106 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
restoreQueries and persisterGc throw on malformed persisted entries対応中かも @VGontier-cmd が 3 日前に担当しました。 オープン
難易度 3/5 1〜2日 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
Add: YRF Music Nepalオープンstreams:add
難易度 1/5 1時間未満 初心者へのやさしさ 62/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
walletbeat/walletbeat#1558 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
hawk-digital-environments/HAWKI#438 ·
メンテナーはふだん 1 日以内に返信
-
Bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
GiganticMinecraft/seichi-portal-frontend#1165 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1〜3時間 初心者へのやさしさ 84/100
メンテナーはふだん 1 日以内に返信