diff --git a/infinite/index.ts b/infinite/index.ts index 112077241..b6600576e 100644 --- a/infinite/index.ts +++ b/infinite/index.ts @@ -4,34 +4,38 @@ import { useRef, useState, useCallback } from 'react' import useSWR, { SWRConfig, - KeyLoader, Fetcher, SWRHook, MutatorCallback, Middleware, - ValueKey, - Result + Arguments } from 'swr' import { useIsomorphicLayoutEffect } from '../src/utils/env' import { serialize } from '../src/utils/serialize' import { isUndefined, isFunction, UNDEFINED } from '../src/utils/helper' import { withMiddleware } from '../src/utils/with-middleware' -import { SWRInfiniteConfiguration, SWRInfiniteResponse } from './types' +import { + SWRInfiniteConfiguration, + SWRInfiniteResponse, + SWRInfiniteHook, + InfiniteKeyLoader, + InfiniteFetcher +} from './types' const INFINITE_PREFIX = '$inf$' -const getFirstPageKey = (getKey: KeyLoader) => { +const getFirstPageKey = (getKey: InfiniteKeyLoader) => { return serialize(getKey ? getKey(0, null) : null)[0] } -export const unstable_serialize = (getKey: KeyLoader) => { +export const unstable_serialize = (getKey: InfiniteKeyLoader) => { return INFINITE_PREFIX + getFirstPageKey(getKey) } -export const infinite = ((( +export const infinite = ((( useSWRNext: SWRHook ) => ( - getKey: KeyLoader, + getKey: InfiniteKeyLoader, fn: Fetcher | null, config: typeof SWRConfig.default & SWRInfiniteConfiguration ): SWRInfiniteResponse => { @@ -250,37 +254,5 @@ export const infinite = ((( } as SWRInfiniteResponse }) as unknown) as Middleware -export type InfiniteFetcher< - Args extends ValueKey = ValueKey, - Data = any -> = Args extends (readonly [...infer K]) - ? ((...args: [...K]) => Result) - : Args extends null - ? never - : Args extends (infer T) - ? (...args: [T]) => Result - : never - -interface SWRInfiniteHook { - ( - getKey: KeyLoader - ): SWRInfiniteResponse - ( - getKey: KeyLoader, - fn: InfiniteFetcher | null - ): SWRInfiniteResponse - ( - getKey: KeyLoader, - config: SWRInfiniteConfiguration | undefined - ): SWRInfiniteResponse - ( - ...args: [ - KeyLoader, - InfiniteFetcher | null, - SWRInfiniteConfiguration | undefined - ] - ): SWRInfiniteResponse -} - export default withMiddleware(useSWR, infinite) as SWRInfiniteHook -export { SWRInfiniteConfiguration, SWRInfiniteResponse } +export { SWRInfiniteConfiguration, SWRInfiniteResponse, InfiniteFetcher } diff --git a/infinite/types.ts b/infinite/types.ts index 93f65031b..e5f60bc9d 100644 --- a/infinite/types.ts +++ b/infinite/types.ts @@ -1,10 +1,27 @@ -import { SWRConfiguration, Fetcher, SWRResponse, ValueKey } from 'swr' +import { SWRConfiguration, SWRResponse, Arguments } from 'swr' + +type FetcherResponse = Data | Promise + +export type InfiniteFetcher< + Args extends Arguments = Arguments, + Data = any +> = Args extends (readonly [...infer K]) + ? ((...args: [...K]) => FetcherResponse) + : Args extends null + ? never + : Args extends (infer T) + ? (...args: [T]) => FetcherResponse + : never + +export type InfiniteKeyLoader = + | ((index: number, previousPageData: any | null) => Args) + | null export type SWRInfiniteConfiguration< Data = any, Error = any, - Args extends ValueKey = ValueKey -> = SWRConfiguration> & { + Args extends Arguments = Arguments +> = SWRConfiguration & { initialSize?: number revalidateAll?: boolean persistSize?: boolean @@ -17,3 +34,26 @@ export interface SWRInfiniteResponse size: number | ((_size: number) => number) ) => Promise } + +export interface SWRInfiniteHook { + ( + getKey: InfiniteKeyLoader + ): SWRInfiniteResponse + ( + getKey: InfiniteKeyLoader, + fetcher: InfiniteFetcher | null + ): SWRInfiniteResponse + ( + getKey: InfiniteKeyLoader, + config: + | SWRInfiniteConfiguration + | undefined + ): SWRInfiniteResponse + ( + getKey: InfiniteKeyLoader, + fetcher: InfiniteFetcher | null, + config: + | SWRInfiniteConfiguration + | undefined + ): SWRInfiniteResponse +} diff --git a/src/index.ts b/src/index.ts index c6a0b56d0..47b5e9831 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,6 +21,5 @@ export { Fetcher, MutatorCallback, Middleware, - ValueKey, - Result + Arguments } from './types' diff --git a/src/types.ts b/src/types.ts index 5ebf1e913..3255d48eb 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,35 +1,33 @@ import * as revalidateEvents from './constants/revalidate-events' -export type Result = T | Promise +export type FetcherResponse = Data | Promise -export type Fetcher = +export type Fetcher = /** * () => [{ foo: string }, { bar: number }] | null - * * () => ( [{ foo: string }, { bar: number } ] as const | null ) */ - Args extends (() => readonly [...infer K] | null) - ? ((...args: [...K]) => Result) + SWRKey extends (() => readonly [...infer Args] | null) + ? ((...args: [...Args]) => FetcherResponse) : /** * [{ foo: string }, { bar: number } ] | null - * * [{ foo: string }, { bar: number } ] as const | null */ - Args extends (readonly [...infer K]) - ? ((...args: [...K]) => Result) + SWRKey extends (readonly [...infer Args]) + ? ((...args: [...Args]) => FetcherResponse) : /** * () => string | null * () => Record | null */ - Args extends (() => infer T | null) - ? (...args: [T]) => Result + SWRKey extends (() => infer Arg | null) + ? (...args: [Arg]) => FetcherResponse : /** * string | null | Record */ - Args extends null + SWRKey extends null ? never - : Args extends (infer T) - ? (...args: [T]) => Result + : SWRKey extends (infer Arg) + ? (...args: [Arg]) => FetcherResponse : never // Configuration types that are only used internally, not exposed to the user. @@ -41,8 +39,7 @@ export interface InternalConfiguration { export interface PublicConfiguration< Data = any, Error = any, - Args extends Key = Key, - Fn = Fetcher + SWRKey extends Key = Key > { errorRetryInterval: number errorRetryCount?: number @@ -59,29 +56,29 @@ export interface PublicConfiguration< shouldRetryOnError: boolean suspense?: boolean fallbackData?: Data - fetcher?: Fn + fetcher?: Fetcher use?: Middleware[] fallback: { [key: string]: any } isPaused: () => boolean onLoadingSlow: ( key: string, - config: Readonly> + config: Readonly> ) => void onSuccess: ( data: Data, key: string, - config: Readonly> + config: Readonly> ) => void onError: ( err: Error, key: string, - config: Readonly> + config: Readonly> ) => void onErrorRetry: ( err: Error, key: string, - config: Readonly>, + config: Readonly>, revalidate: Revalidator, revalidateOpts: Required ) => void @@ -94,55 +91,54 @@ export interface PublicConfiguration< export type FullConfiguration = InternalConfiguration & PublicConfiguration -export type ConfigOptions = { +export type ProviderConfiguration = { initFocus: (callback: () => void) => (() => void) | void initReconnect: (callback: () => void) => (() => void) | void } + export interface SWRHook { - (args: Args): SWRResponse< + (key: SWRKey): SWRResponse< Data, Error > - ( - args: Args, - fn: Fetcher | null + ( + key: SWRKey, + fetcher: Fetcher | null ): SWRResponse - ( - args: Args, - config: SWRConfiguration> | undefined + ( + key: SWRKey, + config: SWRConfiguration | undefined ): SWRResponse - ( - args: Args, - fn: Fetcher, - config: SWRConfiguration> + ( + key: SWRKey, + fetcher: Fetcher, + config: SWRConfiguration | undefined ): SWRResponse - ( + ( ...args: - | [Args] - | [Args, Fetcher | null] - | [ - Args, - SWRConfiguration> | undefined - ] + | [SWRKey] + | [SWRKey, Fetcher | null] + | [SWRKey, SWRConfiguration | undefined] | [ - Args, + SWRKey, Fetcher | null, - SWRConfiguration> + SWRConfiguration | undefined ] ): SWRResponse } // Middlewares guarantee that a SWRHook receives a key, fetcher, and config as the argument -type SWRHookWithMiddleware = ( +export type Middleware = ( + useSWRNext: SWRHook +) => ( key: Args, fetcher: Fetcher | null, config: SWRConfiguration ) => SWRResponse -export type Middleware = (useSWRNext: SWRHook) => SWRHookWithMiddleware -export type TupleKey = [any, ...unknown[]] | readonly [any, ...unknown[]] -export type ValueKey = string | null | TupleKey | Record -export type Key = ValueKey | (() => ValueKey) +type ArgumentsTuple = [any, ...unknown[]] | readonly [any, ...unknown[]] +export type Arguments = string | null | ArgumentsTuple | Record +export type Key = Arguments | (() => Arguments) export type MutatorCallback = ( currentValue?: Data @@ -195,9 +191,8 @@ export type KeyedMutator = ( export type SWRConfiguration< Data = any, Error = any, - Args extends Key = Key, - Fn = Fetcher -> = Partial> + SWRKey extends Key = Key +> = Partial> export interface SWRResponse { data?: Data @@ -206,7 +201,7 @@ export interface SWRResponse { isValidating: boolean } -export type KeyLoader = +export type KeyLoader = | ((index: number, previousPageData: any | null) => Args) | null diff --git a/src/utils/cache.ts b/src/utils/cache.ts index 9ab72660d..75ac78aa3 100644 --- a/src/utils/cache.ts +++ b/src/utils/cache.ts @@ -10,7 +10,7 @@ import { Cache, ScopedMutator, RevalidateCallback, - ConfigOptions + ProviderConfiguration } from '../types' const revalidateAllKeys = ( @@ -24,7 +24,7 @@ const revalidateAllKeys = ( export const initCache = ( provider: Cache, - options?: Partial + options?: Partial ): [Cache, ScopedMutator, () => void] | undefined => { // The global state for a specific provider will be used to deduplicate // requests and store listeners. As well as a mutate function that bound to diff --git a/src/utils/config-context.ts b/src/utils/config-context.ts index 508965c44..42bb5a843 100644 --- a/src/utils/config-context.ts +++ b/src/utils/config-context.ts @@ -7,7 +7,7 @@ import { useIsomorphicLayoutEffect } from './env' import { SWRConfiguration, FullConfiguration, - ConfigOptions, + ProviderConfiguration, Cache } from '../types' @@ -15,7 +15,7 @@ export const SWRConfigContext = createContext>({}) const SWRConfig: FC<{ value?: SWRConfiguration & - Partial & { + Partial & { provider?: (cache: Readonly) => Cache } }> = ({ children, value }) => { diff --git a/src/utils/web-preset.ts b/src/utils/web-preset.ts index 0e41f6a87..29d09b803 100644 --- a/src/utils/web-preset.ts +++ b/src/utils/web-preset.ts @@ -1,4 +1,4 @@ -import { ConfigOptions } from '../types' +import { ProviderConfiguration } from '../types' import { isUndefined, noop, hasWindow, hasDocument } from './helper' /** @@ -62,7 +62,7 @@ export const preset = { isVisible } as const -export const defaultConfigOptions: ConfigOptions = { +export const defaultConfigOptions: ProviderConfiguration = { initFocus, initReconnect }