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'
Equal,Expect: Utility types used for compile-time type assertions.useSWR,useSWRConfig: Hooks from the SWR library to access themutatefunction.Types imported from
swr/_internal: Internal SWR types related to mutation functions, keys, and arguments.expectType: A utility function used for runtime type expectations/checks (likely a type assertion helper).
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>
Case1: Basic mutation function type as defined by SWR'sMutatorFn.Case2-Case6: Variations on a mutation function receiving cache, key, data, and optional options with different shapes/values forpopulateCache.
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>>>
]
This tuple type runs compile-time checks to ensure the
MutatorandMutatorWrappertypes behave as expected.Notably,
Case5is expected to resolve tonever, indicating that mutation functions withpopulateCache: falsein their options do not produce a validMutatorWrappertype.
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 })
}
Demonstrates usage of the
mutatefunction fromuseSWR.Shows allowed mutation calls with async functions returning strings.
Shows TypeScript errors expected when returning a number instead of a string.
Validates correct typing for
populateCacheoption.
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'
})
}
This function demonstrates using
mutatefrom the global SWR config.Shows mutation with predicate keys (function keys) and direct string keys.
Validates expected types of mutation functions and their return types using
expectandexpectType.Covers generic typing of
mutateto ensure correct inference of return values.
Parameters: None
Returns: void
Usage: Type validation example for SWR's global mutate function with various signatures.
Important Implementation Details and Algorithms
Type-Level Testing: The file uses the utility types
ExpectandEqualfrom@type-challenges/utilsfor static type assertions to ensure that types conform to expected behavior.Mutate Function Typings: The different
CaseXtype aliases cover the various overload signatures of themutatefunction in SWR, including variations in options and callback types.TypeScript Error Testing: Usage of
@ts-expect-errorcomments inuseMutatorTypesexplicitly tests that improper calls produce type errors.No Runtime Logic: The file is oriented around type safety and developer experience with SWR's mutation API rather than runtime functionality.
Interaction With Other Parts of the System
SWR Library: This file depends on types and hooks from the
swrpackage, especially internal mutation types and hooks likeuseSWRanduseSWRConfig.Type Utilities: It uses external type utilities (
@type-challenges/utils) and internal helpers (./utils) for type validation.Type Checking Workflow: This file is intended to be part of the development/build process to ensure mutation typings stay correct as SWR evolves.
No Direct Runtime Dependencies: The file exports functions which are primarily for type checking and development-time validation rather than being used in production runtime.
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
mutate.tsis a type-centric utility file ensuring correctness of mutation function typings for the SWR caching library.Defines multiple mutation function signatures and verifies their compatibility via type assertions.
Exports two functions demonstrating correct and incorrect usage of the
mutatefunction in SWR.Plays a crucial role in maintaining strong typing guarantees for developers using SWR's mutation capabilities.
Integrates tightly with SWR's internal mutation types and React hooks.
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.