Mutation Types
Purpose
This subtopic defines the TypeScript types that form the foundation for remote mutation handling within the mutation feature. It addresses the need for strongly-typed mutation fetchers, configuration options, triggers, and mutation responses to enable safe, predictable, and flexible mutation operations. These types provide a clear contract for how mutation hooks are used, what options are supported, and how mutation results and states are exposed to consumers.
By encapsulating mutation-related types separately, the system ensures type safety and extensibility, enabling advanced features such as optimistic updates, conditional cache population, rollback policies, and precise triggering semantics without ambiguity or runtime errors.
Functionality
The core functionality of this subtopic revolves around describing:
MutationFetcher: A generic fetcher function type that accepts a key and an extra argument, returning data synchronously or asynchronously.
SWRMutationConfiguration: Options controlling mutation behavior like revalidation, optimistic updates, rollback, cache population, and lifecycle callbacks.
Trigger Functions: Overloaded function interfaces (
TriggerWithArgs,TriggerWithOptionsArgs,TriggerWithoutArgs) describing how mutations are triggered with optional arguments and error handling behavior.SWRMutationResponse: The shape of the object returned by the mutation hook, exposing mutation state (
data,error,isMutating), atriggerfunction, and aresetfunction.SWRMutationHook: The hook function type signature that consumers use to create mutation hooks, parameterized by data, error, key, extra arguments, and configuration.
These types allow the mutation hook implementation to support:
Flexible trigger signatures that can accept or omit extra arguments.
Optional throwOnError behavior to control error propagation.
Configurable optimistic UI updates and rollback on error.
Cache synchronization based on mutation result.
Lifecycle callbacks (
onSuccessandonError) with typed parameters.
Key Type Relationships
The
MutationFetchertype adapts to the shape of the mutation key, allowing fetchers to receive the appropriate key argument.The
triggerfunction overloads provide different invocation signatures depending on whether extra arguments are required or optional.The
SWRMutationConfigurationtype centralizes mutation behavior options, influencing cache and UI update strategies.The
SWRMutationResponsetype exposes mutation state and control functions to the component using the hook.
Code Snippet Example
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
This snippet illustrates how the fetcher type adapts its key argument based on the form of the mutation key.
Integration
These types integrate closely with the parent topic, Remote Data Mutation, and its other subtopics:
Mutation Hook: The
SWRMutationHooktype directly defines the hook’s function signature, ensuring the hook implementation matches the required behavior and supports type-safe usage in components.Mutation State Management: The
SWRMutationResponseinterface shapes the state returned by the hook, connecting the typed mutation state with React concurrency features and cache updates.Mutation Types supplements the hook and state management by enforcing contracts on mutation triggers, fetchers, and configuration options, thus enabling consistent mutation behavior across the library.
Furthermore, these types are foundational for middleware and utility functions that extend or customize mutation behaviors, such as optimistic UI updates or error rollback strategies. They facilitate strong typing across the mutation ecosystem, reducing bugs and improving developer experience.
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
This class diagram visualizes the core types and their relationships, emphasizing how fetchers, configurations, triggers, responses, and hooks are connected to support the mutation mechanism.