Skip to content

Commit a470f46

Browse files
fix(types): useQueries to also handle array-params with typed QueryKey (#3267)
* fix(types): handle useQueries wrappers with strongly-typed array parameters * test(types): confirm typecheck passes without explicit type for mapped query * test(types): add typecheck on queryFn in mapped query
1 parent efb77d7 commit a470f46

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

src/react/tests/useQueries.test.tsx

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ import {
1919
QueryObserverResult,
2020
QueriesObserver,
2121
QueryFunction,
22+
UseQueryOptions,
23+
QueryKey,
2224
} from '../..'
25+
import { EnsuredQueryKey, QueryFunctionContext } from '../../core'
2326

2427
describe('useQueries', () => {
2528
const queryCache = new QueryCache()
@@ -900,7 +903,8 @@ describe('useQueries', () => {
900903
}
901904
})
902905

903-
it('handles types for QueryFunction factory with strongly typed QueryKey', () => {
906+
it('handles strongly typed queryFn factories and useQueries wrappers', () => {
907+
// QueryKey + queryFn factory
904908
type QueryKeyA = ['queryA']
905909
const getQueryKeyA = (): QueryKeyA => ['queryA']
906910
type GetQueryFunctionA = () => QueryFunction<number, QueryKeyA>
@@ -919,6 +923,28 @@ describe('useQueries', () => {
919923
type SelectorB = (data: string) => [string, number]
920924
const getSelectorB = (): SelectorB => data => [data, +data]
921925

926+
// Wrapper with strongly typed array-parameter
927+
function useWrappedQueries<TQueryFnData, TError, TData, TQueryKey extends QueryKey>(
928+
queries: UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>[]
929+
) {
930+
return useQueries(
931+
queries.map(
932+
// no need to type the mapped query
933+
(query) => {
934+
const { queryFn: fn, queryKey: key, onError: err } = query;
935+
expectType<QueryFunction<TQueryFnData, TQueryKey> | undefined>(fn)
936+
return {
937+
queryKey: key,
938+
onError: err,
939+
queryFn: (ctx: QueryFunctionContext<TQueryKey>) => {
940+
expectType<EnsuredQueryKey<TQueryKey>>(ctx.queryKey)
941+
return fn?.call({}, ctx);
942+
}
943+
}
944+
})
945+
)
946+
}
947+
922948
// @ts-expect-error (Page component is not rendered)
923949
// eslint-disable-next-line
924950
function Page() {
@@ -953,6 +979,14 @@ describe('useQueries', () => {
953979
expectType<QueryObserverResult<[string, number], unknown>>(
954980
withSelector[1]
955981
)
982+
983+
const withWrappedQueries = useWrappedQueries(Array(10).map(() => ({
984+
queryKey: getQueryKeyA(),
985+
queryFn: getQueryFunctionA(),
986+
select: getSelectorA(),
987+
})))
988+
989+
expectType<QueryObserverResult<number | undefined, unknown>[]>(withWrappedQueries);
956990
}
957991
})
958992

src/react/useQueries.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ export type QueriesOptions<
8484
? T
8585
: // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!
8686
// use this to infer the param types in the case of Array.map() argument
87-
T extends UseQueryOptions<infer TQueryFnData, infer TError, infer TData>[]
88-
? UseQueryOptions<TQueryFnData, TError, TData>[]
87+
T extends UseQueryOptions<infer TQueryFnData, infer TError, infer TData, infer TQueryKey>[]
88+
? UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>[]
8989
: // Fallback
9090
UseQueryOptions[]
9191

@@ -104,7 +104,7 @@ export type QueriesResults<
104104
? [...Result, GetResults<Head>]
105105
: T extends [infer Head, ...infer Tail]
106106
? QueriesResults<[...Tail], [...Result, GetResults<Head>], [...Depth, 1]>
107-
: T extends UseQueryOptions<infer TQueryFnData, infer TError, infer TData>[]
107+
: T extends UseQueryOptions<infer TQueryFnData, infer TError, infer TData, any>[]
108108
? // Dynamic-size (homogenous) UseQueryOptions array: map directly to array of results
109109
UseQueryResult<unknown extends TData ? TQueryFnData : TData, TError>[]
110110
: // Fallback

0 commit comments

Comments
 (0)