mutate.ts


Overview

The mutate.ts file is a TypeScript module that provides type definitions, type tests, and usage examples related to mutation operations in the context of the swr (stale-while-revalidate) data fetching library. It focuses primarily on typing and validating the behavior of the mutate function, which is used to update or mutate cached data in SWR's cache.

This file does not implement mutation logic itself but rather defines several type aliases and test cases to verify the correctness and compatibility of different mutation function signatures. It also demonstrates how to use the mutate function with specific typing constraints via two exported functions: useMutatorTypes and useConfigMutate.


Detailed Explanation

Imports and Types

import type { Equal, Expect } from '@type-challenges/utils'
import useSWR, { useSWRConfig } from 'swr'
import type {
  MutatorFn,
  Key,
  MutatorCallback,
  Mutator,
  MutatorWrapper,
  Arguments
} from 'swr/_internal'
import { expectType } from './utils'

Type Aliases for Mutation Function Signatures

These aliases represent different valid forms of mutation functions with varying parameters and options:

type Case1<Data = any> = MutatorFn<Data>
type Case2<Data = any> = (
  cache: Cache,
  key: Key,
  data: Data | Promise<Data> | MutatorCallback<Data>,
  opts: boolean
) => Promise<Data | undefined>
type Case3<Data = any> = (
  cache: Cache,
  key: Key,
  data: Data | Promise<Data> | MutatorCallback<Data>
) => Promise<Data | undefined>
type Case4<Data = any> = (
  cache: Cache,
  key: Key,
  data: Data | Promise<Data> | MutatorCallback<Data>,
  opts: {
    populateCache: undefined
  }
) => Promise<Data | undefined>
type Case5<Data = any> = (
  cache: Cache,
  key: Key,
  data: Data | Promise<Data> | MutatorCallback<Data>,
  opts: {
    populateCache: false
  }
) => Promise<Data | undefined>
type Case6<Data = any> = (
  cache: Cache,
  key: Key,
  data: Data | Promise<Data> | MutatorCallback<Data>,
  opts: {
    populateCache: true
  }
) => Promise<Data | undefined>

Type Assertion Test Cases

export type TestCasesForMutator = [
  Expect<Equal<Mutator<{}>, Promise<{} | undefined>>>,
  Expect<Equal<MutatorWrapper<Case1<{}>>, Promise<{} | undefined>>>,
  Expect<Equal<MutatorWrapper<Case2<{}>>, Promise<{} | undefined>>>,
  Expect<Equal<MutatorWrapper<Case3<{}>>, Promise<{} | undefined>>>,
  Expect<Equal<MutatorWrapper<Case4<{}>>, Promise<{} | undefined>>>,
  Expect<Equal<MutatorWrapper<Case5<{}>>, never>>,
  Expect<Equal<MutatorWrapper<Case6<{}>>, Promise<{} | undefined>>>
]

Function: useMutatorTypes()

export function useMutatorTypes() {
  const { mutate } = useSWR<string>('')

  mutate(async () => '1')
  mutate(async () => '1', { populateCache: false })

  // @ts-expect-error
  mutate(async () => 1)
  // @ts-expect-error
  mutate(async () => 1, { populateCache: false })
}

Parameters: None
Returns: void
Usage: Implicitly validates correct types for SWR's mutate via TypeScript.


Function: useConfigMutate()

export function useConfigMutate() {
  const { mutate } = useSWRConfig()
  expect<Promise<Array<any>>>(
    mutate(
      key => {
        expectType<Arguments>(key)
        return typeof key === 'string' && key.startsWith('swr')
      },
      data => {
        expectType<number | undefined>(data)
        return 0
      }
    )
  )

  expect<Promise<any>>(
    mutate('string', (data?: string) => {
      expectType<string | undefined>(data)
      return '0'
    })
  )

  expect<Promise<Array<number | undefined>>>(
    mutate<number>(
      key => {
        expectType<Arguments>(key)
        return typeof key === 'string' && key.startsWith('swr')
      },
      data => {
        expectType<number | undefined>(data)
        return 0
      }
    )
  )

  expect<Promise<string | undefined>>(
    mutate<string>('string', data => {
      expectType<string | undefined>(data)
      return '0'
    })
  )

  mutate<string>('string', data => {
    expectType<string | undefined>(data)
    return '0'
  })
}

Parameters: None
Returns: void
Usage: Type validation example for SWR's global mutate function with various signatures.


Important Implementation Details and Algorithms


Interaction With Other Parts of the System


Usage Examples

import { useMutatorTypes, useConfigMutate } from './mutate'

// Use in a React component or hook to validate mutate typings
function Component() {
  useMutatorTypes()
  useConfigMutate()
  return null
}

These functions do not produce UI but are used during development to enforce type correctness for SWR's mutate API.


Mermaid Diagram: Flowchart of Functions and Type Relationships

flowchart TD
    A[mutate.ts]
    subgraph Type Aliases
        C1[Case1<Data> = MutatorFn<Data>]
        C2[Case2<Data>]
        C3[Case3<Data>]
        C4[Case4<Data>]
        C5[Case5<Data>]
        C6[Case6<Data>]
    end

    subgraph Type Tests
        T1[TestCasesForMutator]
    end

    subgraph Functions
        F1[useMutatorTypes()]
        F2[useConfigMutate()]
    end

    A --> TypeAliases
    A --> TypeTests
    A --> Functions
    TypeAliases --> T1
    Functions -->|calls| useSWR["useSWR hook"]
    Functions -->|calls| useSWRConfig["useSWRConfig hook"]
    Functions -->|uses| expectType["expectType utility"]

Summary


This documentation should help developers understand the role of mutate.ts in the broader codebase, ensuring better type safety and developer experience when working with SWR's mutate function.