Dani;
Dani;2y ago

data becomes never[] when destructuring with a fallback value

Currently it doesn't seem possible to set a fallback value on a destructured data property, for example:
const { data = [] } = trpc.useQuery(['company.listIds']);
// expecting data to be the inferred type { id: string }[] but instead it's never[]


// This somehow works
const query = trpc.useQuery(['company.listIds']);
const { data = [] } = query;
// data is correctly typed as { id: string }[]
const { data = [] } = trpc.useQuery(['company.listIds']);
// expecting data to be the inferred type { id: string }[] but instead it's never[]


// This somehow works
const query = trpc.useQuery(['company.listIds']);
const { data = [] } = query;
// data is correctly typed as { id: string }[]
The "equivalent" with pure react-query:
interface Company {
id: string;
}
const { data = [] } = useQuery<Company[]>(['company.listIds'], someFetchFunction);
// data is correctly typed as Company[]
interface Company {
id: string;
}
const { data = [] } = useQuery<Company[]>(['company.listIds'], someFetchFunction);
// data is correctly typed as Company[]
Does anyone know if there's a way to achieve the same behaviour of react-query in @trpc/react?
13 Replies
julius
julius2y ago
You can use the initialData prop:
const { data } = trpc.useQuery(["company.listIds"], {
initialData: []
});
const { data } = trpc.useQuery(["company.listIds"], {
initialData: []
});
Dani;
Dani;2y ago
Tried this, while the actual data value at runtime is an array, the type is still
{ id: string }[] | undefined
{ id: string }[] | undefined
julius
julius2y ago
i would think thats cause the initialData is only used for the first fetch? it can become undefined again later? if you also use keepPreviousData it should always be defined i guess 🤔
Dani;
Dani;2y ago
Hm that makes sense, this also seems to be the behaviour with react-query Nope, keepPreviousData doesn't change the type
julius
julius2y ago
cc @TkDodo should the undefined be omitted if both keepPreviousData and initialData is provided or is there some other way to do this?
TkDodo 🔮
TkDodo 🔮2y ago
so with plain TanStack/query, you can use destructuring and assign an empty array and the type will be preserved. you can also use initialData, which will narrow the type and remove undefined from the union. However, be aware that this is semantically different. If you have a staleTime set and provide initialData, there won't be a fetch. Because initialData is treated as any other data that is put into the cache directly (like calling setQueryData). You can read about this in this article: https://tkdodo.eu/blog/placeholder-and-initial-data-in-react-query Lastly, you can pass placeholderData, which will give you a fetch in any case because the data is never persisted. But that also means its potentially undefined because it will rollback to undefined for example if there is an error. Here are the three options in a typescript playground: https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgVwM4FMCKz1QJ5wC+cAZlBCHAOQACMAhgHaoMDGA1gPRTr2swBaAI458VAFDjWEZvBLoYrABYBJeAF44ACgCUALjgAFciGAYAPAEEoUennONkIAEa4AfG7jrPximfQAdDyoEAA2AG7oWgDaAKwANHAAbIkA7AC6OpLSsigYACL0DACMXto6Xp4I4nBwOSyIcAAmRfRl0elEZWhYongxVOzoeFTpifKKqjBZtZyctQtwAHoA-OKE2TINPYUMAExlupWINXVb8EgtDF2aPdi4-dGDw6PjCspqiUjAjMAwwPRQrt6AYOkQZnA5otaqt1ptcjtWgBmQ4VbwnWr1C7NVo3PK9B4DIYjMakd5TL5wMChPjoJRhJq4YGgzqECFQ6GwwhAA
julius
julius2y ago
Just checked on a v10 example and you can assign a default to the data there too and preserve the type. Seems to work the same in tanstack/query as trpc then which is good
julius
julius2y ago
so will assigning an empty array put it in the cache too or what's the difference between that and using initialData? EDIT: nvm says in the post
julius
julius2y ago
actually the initialData one is different 🤔 may look into that later
TkDodo 🔮
TkDodo 🔮2y ago
We've added overloads in v4 to make initialData narrow the type Those live on useQuery so you'd likely have to duplicate the logic?
julius
julius2y ago
we just use the UseQueryResult type. I see you also have a DefinedUseQueryResult which we could probably use without looking too deep into it https://github.com/TanStack/query/blob/afbd6c73776ad2d68b6d5b64ce9888c85c745a90/packages/react-query/src/useQuery.ts#L24-L34
TkDodo 🔮
TkDodo 🔮2y ago
exactly. DefinedUseQueryResult is the one that is used in the overloads where initialData is passed and doesn't return undefined
Alex / KATT 🐱
Interesting, maybe we need overloads too then
More Posts
SyntaxError Unexpected token u in JSON at position 0 with mutationsI'm trying to use trpc client to await a mutation and just keep getting this error. everything worksLosing the type between the client and serverHello everyone, I am new to tRPC and the magic of types in typescript so I am looking for ideas as tMobile app with tRPCWhat's the suggested way of working with tRPC when it comes to mobile apps? How do you ensure that yHow to use trpc react hooks from an external data sourceHi, I have a monorepo, nextjs and keystone cms. The cms has trpc running, and I managed to get it coNextJS & Keystone CMS, issues when connecting both in a monorepoHello everyone, so I have a monorepo with NextJS and keystone cms, both are running trpc v10beta.15Best practices for implementing an offline applicationHey there! I'm building a full stack react-native app with Expo and a tRPC backend. I'd like for thisomehow when move typed function out of the router files, frontend infer type to be any ?this is inferred corrected since they are in the same file. ``` getX: t.procedure.query(() => { retBig companies that use tRPC?Some of my fellow colleagues were wondering if there are any big companies that use tRPC and how matSSG on nextJS when appRouter is made with fastify adapter?```js export const getStaticProps: GetStaticProps = async () => { const ssg = await createSSGHelpeMigrating to V10 from V9If someone has some ideas on what I might have screwed up when trying to bump tRPC for this public s