title: React Query - Combine properties from multiple custom hooks that use useQuery with type safety
body: <p>I have an arbitrary amount of custom hooks that return the query result from useQuery. What I'm trying to do is combine the return values from those hooks into one object with this structure:</p>
  <pre><code>{
    data,
    isLoading,
    isFetching,
    isSuccess,
  }
  </code></pre>
  <p>The data property will be an array created from combining the data properties on all the results.
  This is my current code:</p>
  <pre class="lang-ts prettyprint-override"><code>export function isAnyProperty(
    property: keyof QueryObserverBaseResult&lt;unknown, unknown&gt;,
    ...queries: UseQueryResult&lt;unknown, unknown&gt;[]
  ) {
    return queries.some((query) =&gt; query[property]);
  }
  
  export function combineQueryResults&lt;TData extends unknown[], TQueries extends UseQueryResult&lt;TData&gt;[]&gt;(
    ...queries: TQueries
  ) {
    const data = queries.reduce&lt;TData[]&gt;((acc, query) =&gt; {
      if (query.data === undefined) {
        return acc;
      }
  
      return [...acc, query.data];
    }, []);
  
    return {
      data,
      isLoading: isAnyProperty('isLoading', ...queries),
      isFetching: isAnyProperty('isFetching', ...queries),
      isSuccess: isAnyProperty('isSuccess', ...queries),
    };
  }
  </code></pre>
  <p>I can't get TypeScript to infer the values for <code>TData</code> when I am using rest parameters, and I am not quite sure why. One thing to note is that I did manage to get TypeScript to infer the correct types when <code>data</code> was an array of <code>UseQueryResult</code>, just not one level down with <code>TData</code>.</p>
  <p>For reference, what I get back currently from <code>data</code> is <code>unknown[][]</code>. What I am expecting to get back is of course a tuple with the <code>data</code> values from <code>UseQueryResult</code>. I thought maybe the reduce function removing all undefined values might mess with TypeScript being able to infer the correct values - so I tried it with a simple map as well, which results in <code>data: (unknown[] | undefined)[]</code> - so that didn't work either.</p>
  <p>I also tried this:</p>
  <pre class="lang-ts prettyprint-override"><code>export function combineQueryResults&lt;TData extends unknown[]&gt;(...queries: UseQueryResult&lt;TData&gt;[]) {
    const data = queries.map((query) =&gt; query.data);
  
    return {
      data,
      isLoading: isAnyProperty('isLoading', ...queries),
      isFetching: isAnyProperty('isFetching', ...queries),
      isSuccess: isAnyProperty('isSuccess', ...queries),
    };
  }
  </code></pre>
  <p>But with this code, typescript will only infer the type for the first variable passed to <code>combineQueryResult</code> and results in a <code>Type 'TypeOne[]' is not assignable to type 'TypeTwo[]'</code> error.</p>
  <p>Looks like typescript will infer the type <code>TData</code> when used with <code>UseQueryResult</code>, but not on its own: <a href="https://i.stack.imgur.com/ZHVpz.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ZHVpz.png" alt="enter image description here" /></a></p>
  <p><code>unknown[]</code>, <code>Vod.ConstructedAsset[]</code>, and <code>Group.Union[]</code> are all <code>TData</code>.</p>