Skip to content

Commit 12cc327

Browse files
authored
breaking: Change the fetcher argument to be consistent with the passed key (#1864)
* change the fetcher argument to be consistent with the key * fix test cases * fix type checks
1 parent e734efe commit 12cc327

10 files changed

+102
-88
lines changed

infinite/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export const infinite = (<Data, Error>(useSWRNext: SWRHook) =>
120120

121121
let previousPageData = null
122122
for (let i = 0; i < pageSize; ++i) {
123-
const [pageKey, pageArgs] = serialize(getKey(i, previousPageData))
123+
const [pageKey, pageArg] = serialize(getKey(i, previousPageData))
124124

125125
if (!pageKey) {
126126
// `pageKey` is falsy, stop fetching new pages.
@@ -148,7 +148,7 @@ export const infinite = (<Data, Error>(useSWRNext: SWRHook) =>
148148
!config.compare(originalData[i], pageData))
149149

150150
if (fn && shouldFetchPage) {
151-
pageData = await fn(...pageArgs)
151+
pageData = await fn(pageArg)
152152
cache.set(pageKey, pageData)
153153
}
154154

infinite/types.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,10 @@ export type SWRInfiniteFetcher<
66
Data = any,
77
KeyLoader extends SWRInfiniteKeyLoader = SWRInfiniteKeyLoader
88
> = KeyLoader extends (...args: any[]) => any
9-
? ReturnType<KeyLoader> extends
10-
| readonly [...infer K]
11-
| null
12-
| false
13-
| undefined
14-
? (...args: [...K]) => FetcherResponse<Data>
9+
? ReturnType<KeyLoader> extends readonly [...infer T]
10+
? (args: T) => FetcherResponse<Data>
1511
: ReturnType<KeyLoader> extends infer T | null | false | undefined
16-
? (...args: [T]) => FetcherResponse<Data>
12+
? (args: T) => FetcherResponse<Data>
1713
: never
1814
: never
1915

src/types.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@ export type BareFetcher<Data = unknown> = (
77
export type Fetcher<
88
Data = unknown,
99
SWRKey extends Key = Key
10-
> = SWRKey extends () => readonly [...infer Args] | null | undefined | false
11-
? (...args: [...Args]) => FetcherResponse<Data>
10+
> = SWRKey extends () => readonly [...infer Args]
11+
? (args: Args) => FetcherResponse<Data>
1212
: SWRKey extends readonly [...infer Args]
13-
? (...args: [...Args]) => FetcherResponse<Data>
13+
? (args: Args) => FetcherResponse<Data>
1414
: SWRKey extends () => infer Arg | null | undefined | false
15-
? (...args: [Arg]) => FetcherResponse<Data>
15+
? (args: Arg) => FetcherResponse<Data>
1616
: SWRKey extends null | undefined | false
1717
? never
1818
: SWRKey extends infer Arg
19-
? (...args: [Arg]) => FetcherResponse<Data>
19+
? (args: Arg) => FetcherResponse<Data>
2020
: never
2121

2222
// Configuration types that are only used internally, not exposed to the user.

src/use-swr.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ import {
3333

3434
const WITH_DEDUPE = { dedupe: true }
3535

36+
type DefinitelyTruthy<T> = false extends T
37+
? never
38+
: 0 extends T
39+
? never
40+
: '' extends T
41+
? never
42+
: null extends T
43+
? never
44+
: undefined extends T
45+
? never
46+
: T
47+
3648
export const useSWRHandler = <Data = any, Error = any>(
3749
_key: Key,
3850
fetcher: Fetcher<Data> | null,
@@ -55,9 +67,9 @@ export const useSWRHandler = <Data = any, Error = any>(
5567
// `key` is the identifier of the SWR `data` state, `keyInfo` holds extra
5668
// states such as `error` and `isValidating` inside,
5769
// all of them are derived from `_key`.
58-
// `fnArgs` is an array of arguments parsed from the key, which will be passed
70+
// `fnArg` is the argument/arguments parsed from the key, which will be passed
5971
// to the fetcher.
60-
const [key, fnArgs, keyInfo] = serialize(_key)
72+
const [key, fnArg, keyInfo] = serialize(_key)
6173

6274
// If it's the initial render of this hook.
6375
const initialMountedRef = useRef(false)
@@ -205,7 +217,11 @@ export const useSWRHandler = <Data = any, Error = any>(
205217
}
206218

207219
// Start the request and save the timestamp.
208-
FETCH[key] = [currentFetcher(...fnArgs), getTimestamp()]
220+
// Key must be truthly if entering here.
221+
FETCH[key] = [
222+
currentFetcher(fnArg as DefinitelyTruthy<Key>),
223+
getTimestamp()
224+
]
209225
}
210226

211227
// Wait until the ongoing request is done. Deduplication is also
@@ -342,7 +358,7 @@ export const useSWRHandler = <Data = any, Error = any>(
342358

343359
return true
344360
},
345-
// `setState` is immutable, and `eventsCallback`, `fnArgs`, `keyInfo`,
361+
// `setState` is immutable, and `eventsCallback`, `fnArg`, `keyInfo`,
346362
// and `keyValidating` are depending on `key`, so we can exclude them from
347363
// the deps array.
348364
//

src/utils/serialize.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { isFunction } from './helper'
33

44
import { Key } from '../types'
55

6-
export const serialize = (key: Key): [string, any[], string] => {
6+
export const serialize = (key: Key): [string, Key, string] => {
77
if (isFunction(key)) {
88
try {
99
key = key()
@@ -13,7 +13,9 @@ export const serialize = (key: Key): [string, any[], string] => {
1313
}
1414
}
1515

16-
const args = [].concat(key as any)
16+
// Use the original key as the argument of fether. This can be a stirng or an
17+
// array of values.
18+
const args = key
1719

1820
// If key is not falsy, or not an empty array, hash it.
1921
key =

test/type/fetcher.ts

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -58,28 +58,25 @@ export function useRecord() {
5858
}
5959

6060
export function useTuple() {
61-
useSWR([{ a: '1', b: { c: '3' } }, [1231, '888']], (...keys) => {
61+
useSWR([{ a: '1', b: { c: '3' } }, [1231, '888']], keys => {
62+
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
63+
return keys
64+
})
65+
useSWR(truthy() ? [{ a: '1', b: { c: '3' } }, [1231, '888']] : null, keys => {
6266
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
6367
return keys
6468
})
65-
useSWR(
66-
truthy() ? [{ a: '1', b: { c: '3' } }, [1231, '888']] : null,
67-
(...keys) => {
68-
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
69-
return keys
70-
}
71-
)
7269
useSWR(
7370
truthy() ? [{ a: '1', b: { c: '3' } }, [1231, '888']] : false,
74-
(...keys) => {
71+
keys => {
7572
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
7673
return keys
7774
}
7875
)
7976
}
8077

8178
export function useReadonlyTuple() {
82-
useSWR([{ a: '1', b: { c: '3' } }, [1231, '888']] as const, (...keys) => {
79+
useSWR([{ a: '1', b: { c: '3' } }, [1231, '888']] as const, keys => {
8380
expectType<
8481
[
8582
{
@@ -95,7 +92,7 @@ export function useReadonlyTuple() {
9592
})
9693
useSWR(
9794
truthy() ? ([{ a: '1', b: { c: '3' } }, [1231, '888']] as const) : null,
98-
(...keys) => {
95+
keys => {
9996
expectType<
10097
[
10198
{
@@ -112,7 +109,7 @@ export function useReadonlyTuple() {
112109
)
113110
useSWR(
114111
truthy() ? ([{ a: '1', b: { c: '3' } }, [1231, '888']] as const) : false,
115-
(...keys) => {
112+
keys => {
116113
expectType<
117114
[
118115
{
@@ -250,30 +247,30 @@ export function useReturnRecord() {
250247
export function useReturnTuple() {
251248
useSWR(
252249
() => [{ a: '1', b: { c: '3' } }, [1231, '888']],
253-
(...keys) => {
250+
keys => {
254251
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
255252
return keys
256253
}
257254
)
258255
useSWR(
259256
() => (truthy() ? [{ a: '1', b: { c: '3' } }, [1231, '888']] : null),
260-
(...keys) => {
257+
keys => {
261258
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
262259
return keys
263260
}
264261
)
265262

266263
useSWR(
267264
() => (truthy() ? [{ a: '1', b: { c: '3' } }, [1231, '888']] : false),
268-
(...keys) => {
265+
keys => {
269266
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
270267
return keys
271268
}
272269
)
273270

274271
useSWRInfinite(
275272
index => [{ a: '1', b: { c: '3', d: index } }, [1231, '888']],
276-
(...keys) => {
273+
keys => {
277274
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
278275
return keys[1]
279276
}
@@ -282,7 +279,7 @@ export function useReturnTuple() {
282279
useSWRInfinite(
283280
index =>
284281
truthy() ? [{ a: '1', b: { c: '3', d: index } }, [1231, '888']] : null,
285-
(...keys) => {
282+
keys => {
286283
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
287284
return keys[1]
288285
}
@@ -291,7 +288,7 @@ export function useReturnTuple() {
291288
useSWRInfinite(
292289
index =>
293290
truthy() ? [{ a: '1', b: { c: '3', d: index } }, [1231, '888']] : false,
294-
(...keys) => {
291+
keys => {
295292
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
296293
return keys[1]
297294
}
@@ -301,7 +298,7 @@ export function useReturnTuple() {
301298
export function useReturnReadonlyTuple() {
302299
useSWR(
303300
() => [{ a: '1', b: { c: '3' } }, [1231, '888']] as const,
304-
(...keys) => {
301+
keys => {
305302
expectType<
306303
[
307304
{
@@ -319,9 +316,9 @@ export function useReturnReadonlyTuple() {
319316
useSWR(
320317
() =>
321318
truthy() ? ([{ a: '1', b: { c: '3' } }, [1231, '888']] as const) : null,
322-
(...keys) => {
319+
keys => {
323320
expectType<
324-
[
321+
readonly [
325322
{
326323
readonly a: '1'
327324
readonly b: {
@@ -338,9 +335,9 @@ export function useReturnReadonlyTuple() {
338335
useSWR(
339336
() =>
340337
truthy() ? ([{ a: '1', b: { c: '3' } }, [1231, '888']] as const) : false,
341-
(...keys) => {
338+
keys => {
342339
expectType<
343-
[
340+
readonly [
344341
{
345342
readonly a: '1'
346343
readonly b: {
@@ -356,9 +353,9 @@ export function useReturnReadonlyTuple() {
356353

357354
useSWRInfinite(
358355
() => [{ a: '1', b: { c: '3' } }, [1231, '888']] as const,
359-
(...keys) => {
356+
keys => {
360357
expectType<
361-
[
358+
readonly [
362359
{
363360
readonly a: '1'
364361
readonly b: {
@@ -374,9 +371,9 @@ export function useReturnReadonlyTuple() {
374371
useSWRInfinite(
375372
() =>
376373
truthy() ? ([{ a: '1', b: { c: '3' } }, [1231, '888']] as const) : null,
377-
(...keys) => {
374+
keys => {
378375
expectType<
379-
[
376+
readonly [
380377
{
381378
readonly a: '1'
382379
readonly b: {
@@ -393,9 +390,9 @@ export function useReturnReadonlyTuple() {
393390
useSWRInfinite(
394391
() =>
395392
truthy() ? ([{ a: '1', b: { c: '3' } }, [1231, '888']] as const) : false,
396-
(...keys) => {
393+
keys => {
397394
expectType<
398-
[
395+
readonly [
399396
{
400397
readonly a: '1'
401398
readonly b: {

0 commit comments

Comments
 (0)