Skip to content

Commit

Permalink
fix: type issue when void or undefined is returned from query function (
Browse files Browse the repository at this point in the history
#3541)

* fix(types): fix handling of promise return type in QueryFunctionData

* fix(QueryFunction): return type restrict void and avoid union type distribution

* fix(QueryClient): make setQueryDefaults compatible with adjusted QueryFunction type

* fix(useQueries): correct type inferrence in GetResults with new QueryFunction type

* fix(tests): adjust all test cases which use any or never as query function return type to comply with new QueryFunction type

* fix(tests): change incorrect query function return types of query tests from string to unknown

* feature(useQuery): add test cases covering void and Promise<void> return types

* feature(useQueries): reject void or undefined as query function return type

* feature(useQueries): add test cases for invalid query function return types

* fix tsc error after rebasing lastest beta branch
  • Loading branch information
yss14 committed May 8, 2022
1 parent 6379654 commit 5f80b09
Show file tree
Hide file tree
Showing 14 changed files with 259 additions and 115 deletions.
2 changes: 1 addition & 1 deletion src/core/queryClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ export class QueryClient {

setQueryDefaults(
queryKey: QueryKey,
options: QueryObserverOptions<any, any, any, any>
options: QueryObserverOptions<unknown, any, any, any>
): void {
const result = this.queryDefaults.find(
x => hashQueryKey(queryKey) === hashQueryKey(x.queryKey)
Expand Down
4 changes: 2 additions & 2 deletions src/core/tests/hydration.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe('dehydration and rehydration', () => {
key: [{ nestedKey: 1 }],
})

const fetchDataAfterHydration = jest.fn()
const fetchDataAfterHydration = jest.fn<unknown, unknown[]>()
await hydrationClient.prefetchQuery(['string'], fetchDataAfterHydration, {
staleTime: 1000,
})
Expand Down Expand Up @@ -143,7 +143,7 @@ describe('dehydration and rehydration', () => {
hydrationCache.find(['string', { key: ['string'], key2: 0 }])?.state.data
).toBe('string')

const fetchDataAfterHydration = jest.fn()
const fetchDataAfterHydration = jest.fn<unknown, unknown[]>()
await hydrationClient.prefetchQuery(
['string', { key: ['string'], key2: 0 }],
fetchDataAfterHydration,
Expand Down
31 changes: 19 additions & 12 deletions src/core/tests/query.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ describe('query', () => {

const promise = queryClient.fetchQuery(
key,
async () => {
async (): Promise<unknown> => {
count++
throw new Error(`error${count}`)
},
Expand Down Expand Up @@ -282,7 +282,7 @@ describe('query', () => {
const key = queryKey()

const queryFn = jest.fn<
Promise<void>,
Promise<unknown>,
[QueryFunctionContext<ReturnType<typeof queryKey>>]
>()
const onAbort = jest.fn()
Expand Down Expand Up @@ -339,7 +339,7 @@ describe('query', () => {
test('should not continue if explicitly cancelled', async () => {
const key = queryKey()

const queryFn = jest.fn()
const queryFn = jest.fn<unknown, unknown[]>()

queryFn.mockImplementation(async () => {
await sleep(10)
Expand Down Expand Up @@ -369,7 +369,7 @@ describe('query', () => {
test('should not error if reset while loading', async () => {
const key = queryKey()

const queryFn = jest.fn()
const queryFn = jest.fn<unknown, unknown[]>()

queryFn.mockImplementation(async () => {
await sleep(10)
Expand Down Expand Up @@ -399,7 +399,7 @@ describe('query', () => {
test('should be able to refetch a cancelled query', async () => {
const key = queryKey()

const queryFn = jest.fn()
const queryFn = jest.fn<unknown, unknown[]>()

queryFn.mockImplementation(async () => {
await sleep(50)
Expand Down Expand Up @@ -432,9 +432,12 @@ describe('query', () => {
test('cancelling a rejected query should not have any effect', async () => {
const key = queryKey()

await queryClient.prefetchQuery(key, async () => {
throw new Error('error')
})
await queryClient.prefetchQuery(
key,
async (): Promise<unknown> => {
throw new Error('error')
}
)
const query = queryCache.find(key)!
query.cancel()
await sleep(10)
Expand All @@ -450,16 +453,20 @@ describe('query', () => {
const query = queryCache.find(key)!
expect(query.state.status).toBe('success')

await queryClient.prefetchQuery(key, () => Promise.reject('reject'), {
retry: false,
})
await queryClient.prefetchQuery(
key,
() => Promise.reject<string>('reject'),
{
retry: false,
}
)
expect(query.state.status).toBe('error')

queryClient.prefetchQuery(
key,
async () => {
await sleep(10)
return Promise.reject('reject')
return Promise.reject<unknown>('reject')
},
{ retry: false }
)
Expand Down
4 changes: 3 additions & 1 deletion src/core/tests/queryCache.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ describe('queryCache', () => {
const onError = jest.fn()
const testCache = new QueryCache({ onError })
const testClient = createQueryClient({ queryCache: testCache })
await testClient.prefetchQuery(key, () => Promise.reject('error'))
await testClient.prefetchQuery(key, () =>
Promise.reject<unknown>('error')
)
const query = testCache.find(key)
expect(onError).toHaveBeenCalledWith('error', query)
})
Expand Down
77 changes: 40 additions & 37 deletions src/core/tests/queryClient.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -471,9 +471,12 @@ describe('queryClient', () => {
const key = queryKey()

await expect(
queryClient.fetchQuery(key, async () => {
throw new Error('error')
})
queryClient.fetchQuery(
key,
async (): Promise<unknown> => {
throw new Error('error')
}
)
).rejects.toEqual(new Error('error'))
})

Expand Down Expand Up @@ -666,7 +669,7 @@ describe('queryClient', () => {

const result = await queryClient.prefetchQuery(
key,
async () => {
async (): Promise<unknown> => {
throw new Error('error')
},
{
Expand Down Expand Up @@ -724,7 +727,7 @@ describe('queryClient', () => {
})
try {
await queryClient.fetchQuery(key2, async () => {
return Promise.reject('err')
return Promise.reject<unknown>('err')
})
} catch {}
queryClient.fetchQuery(key1, async () => {
Expand All @@ -734,7 +737,7 @@ describe('queryClient', () => {
try {
queryClient.fetchQuery(key2, async () => {
await sleep(1000)
return Promise.reject('err2')
return Promise.reject<unknown>('err2')
})
} catch {}
queryClient.fetchQuery(key3, async () => {
Expand Down Expand Up @@ -783,7 +786,7 @@ describe('queryClient', () => {
describe('refetchQueries', () => {
test('should not refetch if all observers are disabled', async () => {
const key = queryKey()
const queryFn = jest.fn().mockReturnValue('data')
const queryFn = jest.fn<string, unknown[]>().mockReturnValue('data')
await queryClient.fetchQuery(key, queryFn)
const observer1 = new QueryObserver(queryClient, {
queryKey: key,
Expand All @@ -797,7 +800,7 @@ describe('queryClient', () => {
})
test('should refetch if at least one observer is enabled', async () => {
const key = queryKey()
const queryFn = jest.fn().mockReturnValue('data')
const queryFn = jest.fn<string, unknown[]>().mockReturnValue('data')
await queryClient.fetchQuery(key, queryFn)
const observer1 = new QueryObserver(queryClient, {
queryKey: key,
Expand All @@ -819,8 +822,8 @@ describe('queryClient', () => {
test('should refetch all queries when no arguments are given', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer1 = new QueryObserver(queryClient, {
Expand All @@ -845,8 +848,8 @@ describe('queryClient', () => {
test('should be able to refetch all fresh queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand All @@ -864,8 +867,8 @@ describe('queryClient', () => {
test('should be able to refetch all stale queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand All @@ -884,8 +887,8 @@ describe('queryClient', () => {
test('should be able to refetch all stale and active queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
queryClient.invalidateQueries(key1)
Expand All @@ -906,8 +909,8 @@ describe('queryClient', () => {
test('should be able to refetch all active and inactive queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand All @@ -925,8 +928,8 @@ describe('queryClient', () => {
test('should be able to refetch all active and inactive queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand All @@ -944,8 +947,8 @@ describe('queryClient', () => {
test('should be able to refetch only active queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand All @@ -963,8 +966,8 @@ describe('queryClient', () => {
test('should be able to refetch only inactive queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand All @@ -981,7 +984,7 @@ describe('queryClient', () => {

test('should throw an error if throwOnError option is set to true', async () => {
const key1 = queryKey()
const queryFnError = () => Promise.reject('error')
const queryFnError = () => Promise.reject<unknown>('error')
try {
await queryClient.fetchQuery({
queryKey: key1,
Expand All @@ -1006,8 +1009,8 @@ describe('queryClient', () => {
test('should refetch active queries by default', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand All @@ -1025,8 +1028,8 @@ describe('queryClient', () => {
test('should not refetch inactive queries by default', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand All @@ -1044,8 +1047,8 @@ describe('queryClient', () => {
test('should not refetch active queries when "refetch" is "none"', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand All @@ -1065,8 +1068,8 @@ describe('queryClient', () => {
test('should refetch inactive queries when "refetch" is "inactive"', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand All @@ -1088,8 +1091,8 @@ describe('queryClient', () => {
test('should refetch active and inactive queries when "refetch" is "all"', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
await queryClient.fetchQuery(key1, queryFn1)
await queryClient.fetchQuery(key2, queryFn2)
const observer = new QueryObserver(queryClient, {
Expand Down Expand Up @@ -1216,8 +1219,8 @@ describe('queryClient', () => {
test('should refetch all active queries', async () => {
const key1 = queryKey()
const key2 = queryKey()
const queryFn1 = jest.fn().mockReturnValue('data1')
const queryFn2 = jest.fn().mockReturnValue('data2')
const queryFn1 = jest.fn<string, unknown[]>().mockReturnValue('data1')
const queryFn2 = jest.fn<string, unknown[]>().mockReturnValue('data2')
const observer1 = new QueryObserver(queryClient, {
queryKey: key1,
queryFn: queryFn1,
Expand Down
Loading

0 comments on commit 5f80b09

Please sign in to comment.