Skip to content

Commit d617cce

Browse files
author
ekkoxu
committed
type useSWRInfinite
1 parent 1dda508 commit d617cce

File tree

6 files changed

+170
-48
lines changed

6 files changed

+170
-48
lines changed

immutable/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import useSWR, { Middleware, SWRHook } from 'swr'
1+
import useSWR, { Middleware } from 'swr'
22
import { withMiddleware } from '../src/utils/with-middleware'
33

44
export const immutable: Middleware = useSWRNext => (key, fetcher, config) => {
@@ -9,4 +9,4 @@ export const immutable: Middleware = useSWRNext => (key, fetcher, config) => {
99
return useSWRNext(key, fetcher, config)
1010
}
1111

12-
export default withMiddleware(useSWR as SWRHook, immutable)
12+
export default withMiddleware(useSWR, immutable)

infinite/index.ts

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import useSWR, {
88
Fetcher,
99
SWRHook,
1010
MutatorCallback,
11-
Middleware
11+
Middleware,
12+
ValueKey,
13+
Result
1214
} from 'swr'
1315
import { useIsomorphicLayoutEffect } from '../src/utils/env'
1416
import { serialize } from '../src/utils/serialize'
@@ -18,18 +20,20 @@ import { SWRInfiniteConfiguration, SWRInfiniteResponse } from './types'
1820

1921
const INFINITE_PREFIX = '$inf$'
2022

21-
const getFirstPageKey = (getKey: KeyLoader<any>) => {
23+
const getFirstPageKey = (getKey: KeyLoader) => {
2224
return serialize(getKey ? getKey(0, null) : null)[0]
2325
}
2426

25-
export const unstable_serialize = (getKey: KeyLoader<any>) => {
27+
export const unstable_serialize = (getKey: KeyLoader) => {
2628
return INFINITE_PREFIX + getFirstPageKey(getKey)
2729
}
2830

29-
export const infinite = ((<Data, Error>(useSWRNext: SWRHook) => (
30-
getKey: KeyLoader<Data>,
31+
export const infinite = ((<Data, Error, Args extends ValueKey>(
32+
useSWRNext: SWRHook
33+
) => (
34+
getKey: KeyLoader<Args>,
3135
fn: Fetcher<Data> | null,
32-
config: typeof SWRConfig.default & SWRInfiniteConfiguration<Data, Error>
36+
config: typeof SWRConfig.default & SWRInfiniteConfiguration<Data, Error, Args>
3337
): SWRInfiniteResponse<Data, Error> => {
3438
const rerender = useState({})[1]
3539
const didMountRef = useRef<boolean>(false)
@@ -135,8 +139,7 @@ export const infinite = ((<Data, Error>(useSWRNext: SWRHook) => (
135139
!config.compare(originalData[i], pageData))
136140

137141
if (fn && shouldFetchPage) {
138-
// @ts-ignore since fn here is union type
139-
pageData = await fn.apply(fn, pageArgs)
142+
pageData = await fn(...pageArgs)
140143
cache.set(pageKey, pageData)
141144
}
142145

@@ -247,20 +250,39 @@ export const infinite = ((<Data, Error>(useSWRNext: SWRHook) => (
247250
} as SWRInfiniteResponse<Data, Error>
248251
}) as unknown) as Middleware
249252

250-
type SWRInfiniteHook = <Data = any, Error = any>(
251-
...args:
252-
| readonly [KeyLoader<Data>]
253-
| readonly [KeyLoader<Data>, Fetcher<Data> | null]
254-
| readonly [
255-
KeyLoader<Data>,
256-
SWRInfiniteConfiguration<Data, Error> | undefined
257-
]
258-
| readonly [
259-
KeyLoader<Data>,
260-
Fetcher<Data> | null,
261-
SWRInfiniteConfiguration<Data, Error> | undefined
262-
]
263-
) => SWRInfiniteResponse<Data, Error>
253+
export type InfiniteFetcher<
254+
Args extends ValueKey = ValueKey,
255+
Data = unknown
256+
> = Args extends (readonly [...infer K])
257+
? ((...args: [...K]) => Result<Data>)
258+
: Args extends (string | null)
259+
? Args extends (Record<any, any> | null)
260+
? never
261+
: (...args: [string]) => Result<Data>
262+
: Args extends (infer T)
263+
? (...args: [T]) => Result<Data>
264+
: never
265+
266+
interface SWRInfiniteHook {
267+
<Data = any, Error = any, Args extends ValueKey = ValueKey>(
268+
getKey: KeyLoader<Args>
269+
): SWRInfiniteResponse<Data, Error>
270+
<Data = any, Error = any, Args extends ValueKey = ValueKey>(
271+
getKey: KeyLoader<Args>,
272+
fn: InfiniteFetcher<Args, Data> | null
273+
): SWRInfiniteResponse<Data, Error>
274+
<Data = any, Error = any, Args extends ValueKey = ValueKey>(
275+
getKey: KeyLoader<Args>,
276+
config: SWRInfiniteConfiguration<Data, Error, Args> | undefined
277+
): SWRInfiniteResponse<Data, Error>
278+
<Data = any, Error = any, Args extends ValueKey = ValueKey>(
279+
...args: [
280+
KeyLoader<Args>,
281+
InfiniteFetcher<Args, Data> | null,
282+
SWRInfiniteConfiguration<Data, Error, Args> | undefined
283+
]
284+
): SWRInfiniteResponse<Data, Error>
285+
}
264286

265287
export default withMiddleware(useSWR, infinite) as SWRInfiniteHook
266288
export { SWRInfiniteConfiguration, SWRInfiniteResponse }

infinite/types.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { SWRConfiguration, Fetcher, SWRResponse } from 'swr'
1+
import { SWRConfiguration, Fetcher, SWRResponse, ValueKey } from 'swr'
22

33
export type SWRInfiniteConfiguration<
44
Data = any,
5-
Error = any
6-
> = SWRConfiguration<Data[], Error, Fetcher<Data[]>> & {
5+
Error = any,
6+
Args extends ValueKey = ValueKey
7+
> = SWRConfiguration<Data[], Error, Args, Fetcher<Data[], Args>> & {
78
initialSize?: number
89
revalidateAll?: boolean
910
persistSize?: boolean

src/types.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,32 @@ export type Fetcher<Data = unknown, Args extends Key = Key> =
1010
*/
1111
Args extends (() => readonly [...infer K] | null)
1212
? ((...args: [...K]) => Result<Data>)
13-
/**
14-
* [{ foo: string }, { bar: number } ] | null
15-
*
16-
* [{ foo: string }, { bar: number } ] as const | null
17-
*/
18-
: Args extends (readonly [...infer K])
13+
: /**
14+
* [{ foo: string }, { bar: number } ] | null
15+
*
16+
* [{ foo: string }, { bar: number } ] as const | null
17+
*/
18+
Args extends (readonly [...infer K])
1919
? ((...args: [...K]) => Result<Data>)
20-
/**
21-
* () => string | null
22-
* () => Record<any, any> | null
23-
*/
24-
: Args extends (() => infer T | null)
20+
: /**
21+
* () => string | null
22+
* () => Record<any, any> | null
23+
*/
24+
Args extends (() => infer T | null)
2525
? (...args: [T]) => Result<Data>
26-
/**
27-
* string | null
28-
*/
29-
: Args extends (string | null)
30-
/**
26+
: /**
27+
* string | null
28+
*/
29+
Args extends (string | null)
30+
? /**
3131
* when key is Record<any, any> | null
3232
* use { foo: string, bar: number } | null as example
3333
*
3434
* the fetcher would be
3535
* (arg0: string) => any | (arg0: { foo: string, bar: number }) => any
3636
* so we add this condition to make (arg0: string) => any to be never
3737
*/
38-
? Args extends (Record<any, any> | null)
38+
Args extends (Record<any, any> | null)
3939
? never
4040
: (...args: [string]) => Result<Data>
4141
: Args extends (infer T)
@@ -216,8 +216,8 @@ export interface SWRResponse<Data, Error> {
216216
isValidating: boolean
217217
}
218218

219-
export type KeyLoader<Data = any> =
220-
| ((index: number, previousPageData: Data | null) => ValueKey)
219+
export type KeyLoader<Args extends ValueKey = ValueKey> =
220+
| ((index: number, previousPageData: any | null) => Args)
221221
| null
222222

223223
export interface RevalidatorOptions {

src/use-swr.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,7 @@ export const useSWRHandler = <Data = any, Error = any>(
173173

174174
// Start the request and keep the timestamp.
175175
CONCURRENT_PROMISES_TS[key] = getTimestamp()
176-
// @ts-ignore since fn here is union type
177-
CONCURRENT_PROMISES[key] = fn.apply(fn, fnArgs)
176+
CONCURRENT_PROMISES[key] = fn(...fnArgs)
178177
}
179178

180179
// Wait until the ongoing request is done. Deduplication is also

test-type/fetcher.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import useSWR from 'swr'
2+
import useSWRInfinite from 'swr/infinite'
3+
24
type ExpectType = <T>(value: T) => void
35
const expectType: ExpectType = () => {}
46

@@ -89,6 +91,26 @@ export function useReturnString() {
8991
return key
9092
}
9193
)
94+
95+
useSWRInfinite(
96+
(index, previousPageData: string) => {
97+
return `${index}${previousPageData}`
98+
},
99+
key => {
100+
expectType<string>(key)
101+
return key
102+
}
103+
)
104+
105+
useSWRInfinite(
106+
(index, previousPageData: string) => {
107+
return truthy() ? `${index}${previousPageData}` : null
108+
},
109+
key => {
110+
expectType<string>(key)
111+
return key
112+
}
113+
)
92114
}
93115

94116
export function useReturnRecord() {
@@ -106,6 +128,31 @@ export function useReturnRecord() {
106128
return key
107129
}
108130
)
131+
132+
useSWRInfinite(
133+
index => ({
134+
index,
135+
endPoint: '/api'
136+
}),
137+
key => {
138+
expectType<{ index: number; endPoint: string }>(key)
139+
return [key]
140+
}
141+
)
142+
143+
useSWRInfinite(
144+
index =>
145+
truthy()
146+
? {
147+
index,
148+
endPoint: '/api'
149+
}
150+
: null,
151+
key => {
152+
expectType<{ index: number; endPoint: string }>(key)
153+
return [key]
154+
}
155+
)
109156
}
110157

111158
export function useReturnTuple() {
@@ -123,6 +170,23 @@ export function useReturnTuple() {
123170
return keys
124171
}
125172
)
173+
174+
useSWRInfinite(
175+
index => [{ a: '1', b: { c: '3', d: index } }, [1231, '888']],
176+
(...keys) => {
177+
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
178+
return keys[1]
179+
}
180+
)
181+
182+
useSWRInfinite(
183+
index =>
184+
truthy() ? [{ a: '1', b: { c: '3', d: index } }, [1231, '888']] : null,
185+
(...keys) => {
186+
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
187+
return keys[1]
188+
}
189+
)
126190
}
127191

128192
export function useReturnReadonlyTuple() {
@@ -161,4 +225,40 @@ export function useReturnReadonlyTuple() {
161225
return keys
162226
}
163227
)
228+
229+
useSWRInfinite(
230+
() => [{ a: '1', b: { c: '3' } }, [1231, '888']] as const,
231+
(...keys) => {
232+
expectType<
233+
[
234+
{
235+
readonly a: '1'
236+
readonly b: {
237+
readonly c: '3'
238+
}
239+
},
240+
readonly [1231, '888']
241+
]
242+
>(keys)
243+
return keys
244+
}
245+
)
246+
useSWRInfinite(
247+
() =>
248+
truthy() ? ([{ a: '1', b: { c: '3' } }, [1231, '888']] as const) : null,
249+
(...keys) => {
250+
expectType<
251+
[
252+
{
253+
readonly a: '1'
254+
readonly b: {
255+
readonly c: '3'
256+
}
257+
},
258+
readonly [1231, '888']
259+
]
260+
>(keys)
261+
return keys[1]
262+
}
263+
)
164264
}

0 commit comments

Comments
 (0)