Skip to content

Commit

Permalink
Tweak types (#1640)
Browse files Browse the repository at this point in the history
* test: add test for #1586

Author:    YixuanXu <yixuanxu94@outlook.com>
Date:      Tue Nov 16 19:57:15 2021 +0800

* fix: allow user to use generics

Author:    YixuanXu <yixuanxu94@outlook.com>
Date:      Tue Nov 16 19:58:38 2021 +0800

* chore: remove comments

* fix: allow fallback to origin fetcher

* chore: remove comment

* chore: rename to barefetcher

* add test

Co-authored-by: Shu Ding <g@shud.in>
  • Loading branch information
promer94 and shuding committed Nov 23, 2021
1 parent 4c60fcd commit 34777e5
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 29 deletions.
20 changes: 19 additions & 1 deletion infinite/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SWRConfiguration, SWRResponse, Arguments } from 'swr'
import { SWRConfiguration, SWRResponse, Arguments, BareFetcher } from 'swr'

type FetcherResponse<Data = unknown> = Data | Promise<Data>

Expand All @@ -9,6 +9,8 @@ export type InfiniteFetcher<
? ((...args: [...K]) => FetcherResponse<Data>)
: Args extends null
? never
: Args extends false
? never
: Args extends (infer T)
? (...args: [T]) => FetcherResponse<Data>
: never
Expand Down Expand Up @@ -57,4 +59,20 @@ export interface SWRInfiniteHook {
| SWRInfiniteConfiguration<Data, Error, SWRInfiniteArguments>
| undefined
): SWRInfiniteResponse<Data, Error>
<Data = any, Error = any>(
getKey: InfiniteKeyLoader<Arguments>
): SWRInfiniteResponse<Data, Error>
<Data = any, Error = any>(
getKey: InfiniteKeyLoader<Arguments>,
fetcher: BareFetcher<Data> | null
): SWRInfiniteResponse<Data, Error>
<Data = any, Error = any>(
getKey: InfiniteKeyLoader<Arguments>,
config: SWRInfiniteConfiguration<Data, Error, Arguments> | undefined
): SWRInfiniteResponse<Data, Error>
<Data = any, Error = any>(
getKey: InfiniteKeyLoader<Arguments>,
fetcher: BareFetcher<Data> | null,
config: SWRInfiniteConfiguration<Data, Error, Arguments> | undefined
): SWRInfiniteResponse<Data, Error>
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export {
SWRResponse,
Cache,
SWRHook,
BareFetcher,
Fetcher,
MutatorCallback,
Middleware,
Expand Down
70 changes: 42 additions & 28 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,23 @@
import * as revalidateEvents from './constants/revalidate-events'

export type FetcherResponse<Data = unknown> = Data | Promise<Data>

export type Fetcher<Data = unknown, SWRKey extends Key = Key> =
/**
* () => [{ foo: string }, { bar: number }] | null | undefined | false
* () => ( [{ foo: string }, { bar: number } ] as const | null | undefined | false )
*/
SWRKey extends (() => readonly [...infer Args] | null | undefined | false)
? ((...args: [...Args]) => FetcherResponse<Data>)
: /**
* [{ foo: string }, { bar: number }]
* [{ foo: string }, { bar: number }] as const
*/
SWRKey extends (readonly [...infer Args])
? ((...args: [...Args]) => FetcherResponse<Data>)
: /**
* () => string | null | undefined | false
* () => Record<any, any> | null | undefined | false
*/
SWRKey extends (() => infer Arg | null | undefined | false)
? (...args: [Arg]) => FetcherResponse<Data>
: /**
* string | Record<any,any> | null | undefined | false
*/
SWRKey extends null | undefined | false
? never
: SWRKey extends (infer Arg)
? (...args: [Arg]) => FetcherResponse<Data>
: never
export type BareFetcher<Data = unknown> = (
...args: any[]
) => FetcherResponse<Data>
export type Fetcher<
Data = unknown,
SWRKey extends Key = Key
> = SWRKey extends (() => readonly [...infer Args] | null | undefined | false)
? ((...args: [...Args]) => FetcherResponse<Data>)
: SWRKey extends (readonly [...infer Args])
? ((...args: [...Args]) => FetcherResponse<Data>)
: SWRKey extends (() => infer Arg | null | undefined | false)
? (...args: [Arg]) => FetcherResponse<Data>
: SWRKey extends null | undefined | false
? never
: SWRKey extends (infer Arg)
? (...args: [Arg]) => FetcherResponse<Data>
: never

// Configuration types that are only used internally, not exposed to the user.
export interface InternalConfiguration {
Expand Down Expand Up @@ -126,6 +115,31 @@ export interface SWRHook {
SWRConfiguration<Data, Error, SWRKey> | undefined
]
): SWRResponse<Data, Error>
<Data = any, Error = any>(key: Key): SWRResponse<Data, Error>
<Data = any, Error = any>(
key: Key,
fetcher: BareFetcher<Data> | null
): SWRResponse<Data, Error>
<Data = any, Error = any>(
key: Key,
config: SWRConfiguration<Data, Error> | undefined
): SWRResponse<Data, Error>
<Data = any, Error = any>(
key: Key,
fetcher: BareFetcher<Data>,
config: SWRConfiguration<Data, Error> | undefined
): SWRResponse<Data, Error>
<Data = any, Error = any>(
...args:
| [Key]
| [Key, BareFetcher<Data> | null]
| [Key, SWRConfiguration<Data, Error> | undefined]
| [
Key,
BareFetcher<Data> | null,
SWRConfiguration<Data, Error> | undefined
]
): SWRResponse<Data, Error>
}

// Middlewares guarantee that a SWRHook receives a key, fetcher, and config as the argument
Expand Down
132 changes: 132 additions & 0 deletions test/type/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ const expectType: ExpectType = () => {}

const truthy: () => boolean = () => true

export function useDataErrorGeneric() {
useSWR<{ id: number }>('/api/', () => ({ id: 123 }))
useSWR<string, any>('/api/', (key: string) => key)
}

export function useString() {
useSWR('/api/user', key => {
expectType<string>(key)
Expand All @@ -15,6 +20,11 @@ export function useString() {
expectType<string>(key)
return key
})

useSWR(truthy() ? '/api/user' : false, key => {
expectType<string>(key)
return key
})
}

export function useRecord() {
Expand All @@ -26,6 +36,10 @@ export function useRecord() {
expectType<{ a: string; b: { c: string; d: number } }>(key)
return key
})
useSWR(truthy() ? { a: '1', b: { c: '3', d: 2 } } : false, key => {
expectType<{ a: string; b: { c: string; d: number } }>(key)
return key
})
}

export function useTuple() {
Expand All @@ -40,6 +54,13 @@ export function useTuple() {
return keys
}
)
useSWR(
truthy() ? [{ a: '1', b: { c: '3' } }, [1231, '888']] : false,
(...keys) => {
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
return keys
}
)
}

export function useReadonlyTuple() {
Expand Down Expand Up @@ -74,6 +95,23 @@ export function useReadonlyTuple() {
return keys
}
)
useSWR(
truthy() ? ([{ a: '1', b: { c: '3' } }, [1231, '888']] as const) : false,
(...keys) => {
expectType<
[
{
readonly a: '1'
readonly b: {
readonly c: '3'
}
},
readonly [1231, '888']
]
>(keys)
return keys
}
)
}

export function useReturnString() {
Expand All @@ -92,6 +130,14 @@ export function useReturnString() {
}
)

useSWR(
() => (truthy() ? '/api/user' : false),
key => {
expectType<string>(key)
return key
}
)

useSWRInfinite(
(index, previousPageData: string) => {
return `${index}${previousPageData}`
Expand All @@ -111,6 +157,15 @@ export function useReturnString() {
return key
}
)
useSWRInfinite(
(index, previousPageData: string) => {
return truthy() ? `${index}${previousPageData}` : false
},
key => {
expectType<string>(key)
return key
}
)
}

export function useReturnRecord() {
Expand All @@ -129,6 +184,14 @@ export function useReturnRecord() {
}
)

useSWR(
() => (truthy() ? { a: '1', b: { c: '3', d: 2 } } : false),
key => {
expectType<{ a: string; b: { c: string; d: number } }>(key)
return key
}
)

useSWRInfinite(
index => ({
index,
Expand All @@ -153,6 +216,20 @@ export function useReturnRecord() {
return [key]
}
)

useSWRInfinite(
index =>
truthy()
? {
index,
endPoint: '/api'
}
: false,
key => {
expectType<{ index: number; endPoint: string }>(key)
return [key]
}
)
}

export function useReturnTuple() {
Expand All @@ -171,6 +248,14 @@ export function useReturnTuple() {
}
)

useSWR(
() => (truthy() ? [{ a: '1', b: { c: '3' } }, [1231, '888']] : false),
(...keys) => {
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
return keys
}
)

useSWRInfinite(
index => [{ a: '1', b: { c: '3', d: index } }, [1231, '888']],
(...keys) => {
Expand All @@ -187,6 +272,15 @@ export function useReturnTuple() {
return keys[1]
}
)

useSWRInfinite(
index =>
truthy() ? [{ a: '1', b: { c: '3', d: index } }, [1231, '888']] : false,
(...keys) => {
expectType<[{ a: string; b: { c: string } }, (string | number)[]]>(keys)
return keys[1]
}
)
}

export function useReturnReadonlyTuple() {
Expand Down Expand Up @@ -226,6 +320,25 @@ export function useReturnReadonlyTuple() {
}
)

useSWR(
() =>
truthy() ? ([{ a: '1', b: { c: '3' } }, [1231, '888']] as const) : false,
(...keys) => {
expectType<
[
{
readonly a: '1'
readonly b: {
readonly c: '3'
}
},
readonly [1231, '888']
]
>(keys)
return keys
}
)

useSWRInfinite(
() => [{ a: '1', b: { c: '3' } }, [1231, '888']] as const,
(...keys) => {
Expand Down Expand Up @@ -261,4 +374,23 @@ export function useReturnReadonlyTuple() {
return keys[1]
}
)

useSWRInfinite(
() =>
truthy() ? ([{ a: '1', b: { c: '3' } }, [1231, '888']] as const) : false,
(...keys) => {
expectType<
[
{
readonly a: '1'
readonly b: {
readonly c: '3'
}
},
readonly [1231, '888']
]
>(keys)
return keys[1]
}
)
}

0 comments on commit 34777e5

Please sign in to comment.