I'm using a list of queries with react-query to fetch "dependencies" and I want all the dependencies to load before rendering my component. I get the success state by checking all the deps as array and then act on it:
function DepsLoader() {
const q1 = useQuery()
const q2 = useQuery()
const q3 = useQuery()
const q4 = useQuery()
const deps = [q1, q2, q3, q4]
const allDone = deps.every(dep => dep.isSuccess)
if (!allDone) return <Loading />
return <Component q1={q1.data} q2={q2.data} q3={q3.data} q4={q4.data} />
}
In JS land, this works just fine. However, if I want to do the same in TS, I get an obvious error, that q1.data
is Data | undefined
because it is. Normally, one is supposed to narrow it down by first checking for q1.isSuccess
directly, but in case of my list of dependencies, I don't want to do it manually (in real component, the list can be up to 9 queries atm).
I can as well cast it using q1={q1.data as Q1Type}
but it's not ergonomic.
Is there any way to make TS recognise the fact that in reality all the queries are in success state and I have narrowed it down?
you would need to perform type narrowing with a user defined type guard when executing .every
, because TypeScript doesn't know that without it.
Here is a typescript playground showing the gist of it, based on this StackOverflow answer.