types.ts


Overview

The types.ts file defines TypeScript types, interfaces, and type aliases essential for the infinite loading feature in the SWR (stale-while-revalidate) data fetching library ecosystem. It provides precise typings for the infinite loading hook (useSWRInfinite), its configuration options, fetchers, responses, mutation behaviors, and cache state extensions.

This file is purely about type declarations and does not contain runtime logic or implementations. Its purpose is to enforce strong type safety, provide clear API contracts, and enable rich developer experience (including autocomplete and compile-time checks) when working with paginated or infinite data fetching scenarios.


Detailed Explanation of Types and Interfaces

Core Type Aliases and Interfaces


FetcherResponse<Data = unknown>

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

SWRInfiniteKeyLoader<Data = any, Args extends Arguments = Arguments>

export type SWRInfiniteKeyLoader<
  Data = any,
  Args extends Arguments = Arguments
> = (index: number, previousPageData: Data | null) => Args
const getKey: SWRInfiniteKeyLoader<User[]> = (pageIndex, previousPageData) => {
  if (previousPageData && !previousPageData.length) return null; // No more pages
  return ['api/users', pageIndex];
};

SWRInfiniteFetcher<Data, KeyLoader>

export type SWRInfiniteFetcher<
  Data = any,
  KeyLoader extends SWRInfiniteKeyLoader = SWRInfiniteKeyLoader
> = KeyLoader extends (...args: any[]) => any
  ? ReturnType<KeyLoader> extends infer T | null | false | undefined
    ? (args: T) => FetcherResponse<Data>
    : never
  : never
const fetcher: SWRInfiniteFetcher<User[], typeof getKey> = ([url, page]) =>
  fetch(`${url}?page=${page}`).then(res => res.json());

SWRInfiniteCompareFn<Data>

export interface SWRInfiniteCompareFn<Data = any> {
  (a: Data | undefined, b: Data | undefined): boolean
  (a: Data[] | undefined, b: Data[] | undefined): boolean
}

SWRInfiniteConfiguration<Data, Error, Fn>

export interface SWRInfiniteConfiguration<
  Data = any,
  Error = any,
  Fn extends SWRInfiniteFetcher<Data> = BareFetcher<Data>
> extends Omit<SWRConfiguration<Data[], Error>, 'compare'> {
  initialSize?: number
  revalidateAll?: boolean
  persistSize?: boolean
  revalidateFirstPage?: boolean
  parallel?: boolean
  fetcher?: Fn
  compare?: SWRInfiniteCompareFn<Data>
}

SWRInfiniteRevalidateFn<Data>

interface SWRInfiniteRevalidateFn<Data = any> {
  (data: Data, key: Arguments): boolean
}

SWRInfiniteKeyedMutator<Data>

export type SWRInfiniteKeyedMutator<Data> = <MutationData = Data>(
  data?: Data | Promise<Data | undefined> | MutatorCallback<Data>,
  opts?: boolean | SWRInfiniteMutatorOptions<Data, MutationData>
) => Promise<Data | MutationData | undefined>

SWRInfiniteMutatorOptions<Data, MutationData>

export interface SWRInfiniteMutatorOptions<Data = any, MutationData = Data>
  extends Omit<MutatorOptions<Data, MutationData>, 'revalidate'> {
  revalidate?:
    | boolean
    | SWRInfiniteRevalidateFn<Data extends unknown[] ? Data[number] : never>
}

SWRInfiniteResponse<Data, Error>

export interface SWRInfiniteResponse<Data = any, Error = any>
  extends Omit<SWRResponse<Data[], Error>, 'mutate'> {
  size: number
  setSize: (
    size: number | ((_size: number) => number)
  ) => Promise<Data[] | undefined>
  mutate: SWRInfiniteKeyedMutator<Data[]>
}

SWRInfiniteHook

export interface SWRInfiniteHook {
  // Overloads supporting:
  // - getKey only
  // - getKey + fetcher
  // - getKey + config
  // - getKey + fetcher + config
  // with appropriate typings for Data, Error, KeyLoader, fetcher, and config.
}

SWRInfiniteCacheValue<Data, Error>

export interface SWRInfiniteCacheValue<Data = any, Error = any>
  extends State<Data, Error> {
  _i?: boolean            // Flag indicating infinite key context
  _l?: number             // Cached page size (number of pages)
  _k?: Arguments          // Cached key arguments for the first page
  _r?: boolean | SWRInfiniteRevalidateFn // Revalidation flag or function
}

Important Implementation Details and Algorithms (Contextual Notes)

Although this file contains only types, the design reflects key infinite-loading mechanisms:


Interactions with Other System Parts


Usage Example (Simplified)

import type { SWRInfiniteKeyLoader, SWRInfiniteFetcher, SWRInfiniteResponse } from './types';

const getKey: SWRInfiniteKeyLoader<User[]> = (pageIndex, previousPageData) => {
  if (previousPageData && !previousPageData.length) return null; // End pagination
  return [`/api/users?page=${pageIndex}`];
};

const fetcher: SWRInfiniteFetcher<User[]> = (args) => fetch(args[0]).then(res => res.json());

function Component() {
  const { data, size, setSize, mutate }: SWRInfiniteResponse<User[]> = useSWRInfinite(getKey, fetcher);

  return (
    <>
      {data?.map((page, i) => (
        <UserList key={i} users={page} />
      ))}
      <button onClick={() => setSize(size + 1)}>Load More</button>
    </>
  );
}

Mermaid Class Diagram: Structure of types.ts

classDiagram
    class SWRInfiniteHook {
        +getKey: SWRInfiniteKeyLoader
        +fetcher?: SWRInfiniteFetcher
        +config?: SWRInfiniteConfiguration
        +returns SWRInfiniteResponse
    }

    class SWRInfiniteKeyLoader {
        +index: number
        +previousPageData: Data | null
        +returns Args
    }

    class SWRInfiniteFetcher {
        +args: Args
        +returns Data | Promise<Data>
    }

    class SWRInfiniteConfiguration {
        +initialSize: number
        +revalidateAll: boolean
        +persistSize: boolean
        +revalidateFirstPage: boolean
        +parallel: boolean
        +fetcher: SWRInfiniteFetcher
        +compare: SWRInfiniteCompareFn
    }

    class SWRInfiniteResponse {
        +size: number
        +setSize(size)
        +mutate(data, opts)
    }

    class SWRInfiniteCacheValue {
        +_i: boolean
        +_l: number
        +_k: Arguments
        +_r: boolean | SWRInfiniteRevalidateFn
    }

    SWRInfiniteHook --> SWRInfiniteKeyLoader : uses
    SWRInfiniteHook --> SWRInfiniteFetcher : optionally uses
    SWRInfiniteHook --> SWRInfiniteConfiguration : optionally uses
    SWRInfiniteHook --> SWRInfiniteResponse : returns
    SWRInfiniteResponse --> SWRInfiniteKeyedMutator : mutate type
    SWRInfiniteConfiguration --> SWRInfiniteFetcher : fetcher type

Summary

The types.ts file is foundational for the infinite loading feature in SWR, defining comprehensive and flexible typings for:

These types enable robust, type-safe infinite scrolling and pagination patterns with SWR and integrate closely with the core SWR architecture and caching mechanisms. They serve as a contract between the infinite loading implementation, the fetchers, and consumers of the useSWRInfinite hook.


End of Documentation for types.ts