types.ts
Overview
types.ts defines the TypeScript type declarations and interfaces that underpin the Remote Data Mutation functionality within the SWR ecosystem. This file provides a comprehensive and strongly-typed contract for mutation fetchers, mutation hook configurations, trigger functions, and mutation hook responses.
The types in this file enable flexible, type-safe remote mutations in React applications using SWR by specifying:
How mutation fetchers are typed based on the mutation key.
Configuration options controlling mutation behavior (e.g., revalidation, optimistic updates).
Signatures for trigger functions that invoke mutations with or without extra arguments.
The shape of the mutation hook's response object exposing mutation state and control functions.
The mutation hook function signature itself.
By isolating these mutation-related types, the system ensures consistent, extensible, and safe usage of mutation hooks across the codebase and by consumers.
Detailed Type Explanations
1. FetcherResponse<Data>
type FetcherResponse<Data> = Data | Promise<Data>
Purpose: Represents the possible return values from a mutation fetcher, which can be synchronous (
Data) or asynchronous (Promise<Data>).Usage: Used as the return type of fetcher functions that perform remote mutations.
2. FetcherOptions<ExtraArg = unknown>
type FetcherOptions<ExtraArg = unknown> = Readonly<{
arg: ExtraArg
}>
Purpose: Defines the shape of the options object passed to the mutation fetcher, containing an extra argument.
Parameters:
arg: An extra argument of any user-defined type passed to the fetcher.
Usage: Ensures the fetcher receives a consistent options object with a read-only
argproperty.
3. MutationFetcher
export type MutationFetcher<
Data = unknown,
SWRKey extends Key = Key,
ExtraArg = unknown
> = SWRKey extends () => infer Arg | null | undefined | false
? (key: Arg, options: FetcherOptions<ExtraArg>) => FetcherResponse<Data>
: SWRKey extends null | undefined | false
? never
: SWRKey extends infer Arg
? (key: Arg, options: FetcherOptions<ExtraArg>) => FetcherResponse<Data>
: never
Purpose: Defines the type of the mutation fetcher function used to perform remote mutations.
Parameters:
Data: The type of data returned by the fetcher.SWRKey: The key identifying the resource (extendsKey).ExtraArg: An extra argument type passed to the fetcher.
Behavior:
If
SWRKeyis a function returning an argument typeArg(ornull/undefined/false), the fetcher receivesArgaskey.If
SWRKeyisnull/undefined/false, the fetcher type resolves tonever(invalid).Otherwise, the fetcher receives
SWRKeyitself as the key.
Usage Example:
const fetcher: MutationFetcher<UserData, string, FormInput> = (key, { arg }) => {
return fetch(key, {
method: 'POST',
body: JSON.stringify(arg),
}).then(res => res.json());
};
4. SWRMutationConfiguration
export type SWRMutationConfiguration<
Data,
Error,
SWRMutationKey extends Key = Key,
ExtraArg = any,
SWRData = any
> = { ... }
Purpose: Defines configuration options that customize the behavior of the mutation hook.
Properties:
revalidate?: boolean | ((data: Data, key: Arguments) => boolean)Controls whether to revalidate the SWR cache after mutation.
populateCache?: boolean | ((result: Data, currentData: SWRData | undefined) => SWRData)Whether and how to populate the cache with the mutation result.
optimisticData?: SWRData | ((currentData?: SWRData) => SWRData)Data or updater function for optimistic UI updates before mutation resolves.
rollbackOnError?: boolean | ((error: unknown) => boolean)Whether to rollback optimistic updates on error.
fetcher?: MutationFetcher<Data, SWRMutationKey, ExtraArg>Custom fetcher function to override the default.
onSuccess?: (data: Data, key: string, config: Readonly<...>) => voidCallback invoked on mutation success.
onError?: (err: Error, key: string, config: Readonly<...>) => voidCallback invoked on mutation failure.
Usage Example:
const config: SWRMutationConfiguration<User, Error, string, FormData, User> = {
revalidate: true,
optimisticData: currentUser => ({ ...currentUser, name: "Loading..." }),
rollbackOnError: true,
onSuccess: (data) => console.log('Mutation succeeded:', data),
onError: (error) => console.error('Mutation failed:', error),
};
5. Utility Types: RemoveUndefined and IsUndefinedIncluded
type RemoveUndefined<T> = T extends undefined ? never : T
type IsUndefinedIncluded<T> = undefined extends T ? true : false
Purpose:
RemoveUndefined<T>removesundefinedfrom a union typeT.IsUndefinedIncluded<T>is a boolean type indicating whetherundefinedis part of typeT.
Usage:
Used internally to refine return types of trigger functions based on error handling options.
6. Trigger Function Interfaces
These interfaces define multiple overloads for the trigger function used to perform mutations with varying argument presence and error handling.
a. TriggerWithArgs
export interface TriggerWithArgs<
Data = any,
Error = any,
SWRMutationKey extends Key = Key,
ExtraArg = never
> {
<SWRData = Data>(extraArgument: ExtraArg, options?: SWRMutationConfiguration<...>): Promise<Data>
<SWRData = Data>(extraArgument: ExtraArg, options?: SWRMutationConfiguration<...> & { throwOnError: true }): Promise<RemoveUndefined<Data>>
<SWRData = Data>(extraArgument: ExtraArg, options?: SWRMutationConfiguration<...> & { throwOnError: false }): Promise<Data | undefined>
}
Purpose: Trigger function for mutations requiring an extra argument.
Parameters:
extraArgument: ExtraArg: The argument passed to the fetcher.options: Optional mutation configuration overrides, includingthrowOnError.
Return:
Returns a
Promiseresolving to mutation data, optionally refined bythrowOnError.
Usage Example:
await trigger({ name: 'Alice' }, { throwOnError: true });
b. TriggerWithOptionsArgs
export interface TriggerWithOptionsArgs<...> { ... }
Purpose: Trigger function for mutations with optional extra arguments.
Parameters:
extraArgument?: ExtraArg(optional).
Usage:
await trigger(undefined, options);
await trigger({ id: 123 });
c. TriggerWithoutArgs
export interface TriggerWithoutArgs<...>{ ... }
Purpose: Trigger function for mutations that do not require extra arguments (extraArgument is
nullor omitted).Usage:
await trigger();
await trigger(null);
7. SWRMutationResponse
export interface SWRMutationResponse<
Data = any,
Error = any,
SWRMutationKey extends Key = Key,
ExtraArg = never
> extends Pick<SWRResponse<Data, Error>, 'data' | 'error'> {
isMutating: boolean
trigger: /* one of TriggerWithArgs, TriggerWithOptionsArgs, TriggerWithoutArgs based on ExtraArg */
reset: () => void
}
Purpose: Defines the shape of the object returned from the mutation hook.
Properties:
data: The latest mutation data.error: The latest mutation error.isMutating: Boolean flag indicating if a mutation is in progress.trigger: Function to initiate a mutation with appropriate signature based onExtraArg.reset(): Function to reset mutation state (data,error,isMutating).
Usage:
const { data, error, isMutating, trigger, reset } = useSWRMutation(...);
await trigger(extraArg, options);
reset();
8. SWRMutationHook
export interface SWRMutationHook {
<
Data = any,
Error = any,
SWRMutationKey extends Key = Key,
ExtraArg = never,
SWRData = Data
>(
key: SWRMutationKey,
fetcher: MutationFetcher<Data, SWRMutationKey, ExtraArg>,
options?: SWRMutationConfiguration<Data, Error, SWRMutationKey, ExtraArg, SWRData> & { throwOnError?: boolean }
): SWRMutationResponse<Data, Error, SWRMutationKey, ExtraArg>
// Overloads with throwOnError true/false for refined return types
}
Purpose: Describes the function signature of the mutation hook exposed to consumers.
Parameters:
key: The resource key, must correspond to the SWR cache key.fetcher: The mutation fetcher function.options: Optional configuration includingthrowOnError.
Returns: An
SWRMutationResponseobject exposing mutation state and trigger/reset functions.Usage Example:
const mutation = useSWRMutation('/api/user', fetcher, { optimisticData: {...} });
Important Implementation Details
The
MutationFetchertype dynamically adapts to the shape ofSWRKeyto ensure type-safe fetcher signatures.Multiple overloads for trigger functions allow flexible usage with or without extra arguments, and with explicit error throwing control (
throwOnError).The
SWRMutationResponse.triggerfunction's type is conditionally selected based on whetherExtraArgisnever, includesundefined, or is required.The
resetfunction allows clearing mutation state to initial values.The
SWRMutationConfigurationtype supports advanced mutation behaviors such as optimistic updates, rollback on error, cache population, and lifecycle callbacks, facilitating robust remote mutation workflows.
Interaction with Other Parts of the System
Integration with
useSWRand SWR Cache: The mutation types are foundational to the mutation hook (useSWRMutation) implementation, which is a middleware-enhanced version ofuseSWR. These types ensure that mutations integrate seamlessly with SWR's caching and revalidation mechanisms.Relation to Remote Data Mutation Module: This file provides the contract that the mutation hook and state management modules rely upon to implement mutation workflows, optimistic updates, and error handling.
Dependency on Core Types: Types like
Key,Arguments, andSWRResponseare imported from the core SWR index, ensuring consistent typing across the library.Used by Middleware and Utility Functions: Middleware that implements mutation logic utilizes these types to enforce correct fetcher signatures and mutation configuration handling.
Exposed to Consumers: These types are part of the public API surface, enabling developers to write strongly-typed mutations in their React components.
Usage Examples
Defining a Mutation Fetcher
type UserData = { id: number; name: string };
type UpdateUserPayload = { name: string };
const updateUserFetcher: MutationFetcher<UserData, string, UpdateUserPayload> = (key, { arg }) => {
return fetch(key, {
method: 'PUT',
body: JSON.stringify(arg),
}).then(res => res.json());
};
Using the Mutation Hook
const { data, error, isMutating, trigger, reset } = useSWRMutation(
'/api/user/123',
updateUserFetcher,
{
optimisticData: { id: 123, name: 'Loading...' },
rollbackOnError: true,
onSuccess: (data) => console.log('User updated:', data),
}
);
await trigger({ name: 'Alice' }, { throwOnError: true });
Mermaid Class Diagram
classDiagram
class MutationFetcher {
<<type>>
+ (key: Arg, options: FetcherOptions) => Data | Promise<Data>
}
class SWRMutationConfiguration {
+ revalidate: boolean | function
+ populateCache: boolean | function
+ optimisticData: any | function
+ rollbackOnError: boolean | function
+ fetcher: MutationFetcher
+ onSuccess(data, key, config): void
+ onError(error, key, config): void
}
class TriggerFunction {
<<interface>>
+ (extraArgument?, options?): Promise<Data | undefined>
}
class SWRMutationResponse {
+ data
+ error
+ isMutating: boolean
+ trigger: TriggerFunction
+ reset(): void
}
class SWRMutationHook {
<<function>>
+ (key, fetcher, options?): SWRMutationResponse
}
MutationFetcher <|-- SWRMutationConfiguration : uses
SWRMutationConfiguration <-- TriggerFunction : uses
TriggerFunction <-- SWRMutationResponse : exposes
SWRMutationResponse <-- SWRMutationHook : returns
Summary
The types.ts file encapsulates the essential TypeScript types for SWR's remote mutation feature, enabling:
Strongly-typed mutation fetchers adaptable to various key shapes.
Rich mutation configuration options for advanced behaviors.
Versatile trigger function signatures supporting different argument and error handling patterns.
A consistent, typed interface for the mutation hook’s API (
useSWRMutation).Clear contracts that facilitate integration with SWR's core caching and data fetching mechanisms.
This type layer is critical for building robust, type-safe mutation hooks that developers can confidently use to perform remote data mutations with predictable semantics and rich feature support.