Releases: apollographql/apollo-client
@apollo/[email protected]
Patch Changes
- #13202
8a51ea6Thanks @phryneas! - Ship agent skill for usage with @tanstack/intent — the skill is now bundled in the npm package underskills/apollo-client/and discoverable byintent list.
For more context, see the TanStack Intent QuickStart.
@apollo/[email protected]
Minor Changes
-
#13132
f3ce805Thanks @phryneas! - Introduce "classic" and "modern" method and hook signatures.Apollo Client 4.2 introduces two signature styles for methods and hooks. All signatures previously present are now "classic" signatures, and a new set of "modern" signatures are added alongside them.
Classic signatures are the default and are identical to the signatures before Apollo Client 4.2, preserving backward compatibility. Classic signatures still work with manually specified TypeScript generics (e.g.,
useSuspenseQuery<MyData>(...)). However, manually specifying generics has been discouraged for a long time—instead, we recommend usingTypedDocumentNodeto automatically infer types, which provides more accurate results without any manual annotations.Modern signatures automatically incorporate your declared
defaultOptionsinto return types, providing more accurate types. Modern signatures infer types from the document node and do not support manually passing generic type arguments; TypeScript will produce a type error if you attempt to do so.Methods and hooks automatically switch to modern signatures the moment any non-optional property is declared in
DeclareDefaultOptions. The switch happens across all methods and hooks globally:// apollo.d.ts import "@apollo/client"; declare module "@apollo/client" { namespace ApolloClient { namespace DeclareDefaultOptions { interface WatchQuery { errorPolicy: "all"; // non-optional → modern signatures activated automatically } } } }
Users can also manually switch to modern signatures without declaring any
defaultOptions, for example when wanting accurate type inference without relying on globaldefaultOptions:// apollo.d.ts import "@apollo/client"; declare module "@apollo/client" { export interface TypeOverrides { signatureStyle: "modern"; } }
Users can do a global
DeclareDefaultOptionstype augmentation and then manually switch back to "classic" for migration purposes:// apollo.d.ts import "@apollo/client"; declare module "@apollo/client" { export interface TypeOverrides { signatureStyle: "classic"; } }
Note that this is not recommended for long-term use. When combined with
DeclareDefaultOptions, switching back to classic results in the same incorrect types as before Apollo Client 4.2—methods and hooks will not reflect thedefaultOptionsyou've declared. -
#13132
f3ce805Thanks @phryneas! - Synchronize method and hook return types withdefaultOptions.Prior to this change, the following code snippet would always apply:
declare const MY_QUERY: TypedDocumentNode<TData, TVariables>; const result1 = useSuspenseQuery(MY_QUERY); result1.data; // ^? TData const result2 = useSuspenseQuery(MY_QUERY, { errorPolicy: "all" }); result2.data; // ^? TData | undefined
While these types are generally correct, if you were to set
errorPolicy: 'all'as a default option, the type ofresult.datafor the first query would remainTDatainstead of changing toTData | undefinedto match the runtime behavior.We are now enforcing that certain
defaultOptionstypes need to be registered globally. This means that if you want to useerrorPolicy: 'all'as a default option for a query, you will need to register its type like this:// apollo.d.ts import "@apollo/client"; declare module "@apollo/client" { namespace ApolloClient { namespace DeclareDefaultOptions { interface WatchQuery { // possible global-registered values: // * `errorPolicy` // * `returnPartialData` errorPolicy: "all"; } interface Query { // possible global-registered values: // * `errorPolicy` } interface Mutate { // possible global-registered values: // * `errorPolicy` } } } }
Once this type declaration is in place, the type of
result.datain the above example will correctly be changed toTData | undefined, reflecting the possibility that if an error occurs,datamight beundefined. Manually specifyinguseSuspenseQuery(MY_QUERY, { errorPolicy: "none" });changesresult.datatoTDatato reflect the local override.This change means that you will need to declare your default options types in order to use
defaultOptionswithApolloClient, otherwise you will see a TypeScript error.Without the type declaration, the following (previously valid) code will now error:
new ApolloClient({ link: ApolloLink.empty(), cache: new InMemoryCache(), defaultOptions: { watchQuery: { // results in a type error: // Type '"all"' is not assignable to type '"A default option for watchQuery.errorPolicy must be declared in ApolloClient.DeclareDefaultOptions before usage. See https://www.apollographql.com/docs/react/data/typescript#declaring-default-options-for-type-safety."'. errorPolicy: "all", }, }, });
If you are creating multiple instances of Apollo Client with conflicting default options and you cannot register a single
defaultOptionsvalue as a result, you can relax the constraints by declaring those options as union types covering all values used by all clients. The properties can be required (to enforce them indefaultOptions) or optional (if some constructor calls won't pass a value):// apollo.d.ts import "@apollo/client"; declare module "@apollo/client" { export namespace ApolloClient { export namespace DeclareDefaultOptions { interface WatchQuery { errorPolicy?: "none" | "all" | "ignore"; returnPartialData?: boolean; } interface Query { errorPolicy?: "none" | "all" | "ignore"; } interface Mutate { errorPolicy?: "none" | "all" | "ignore"; } } } }
With this declaration, the
ApolloClientconstructor accepts any of those values indefaultOptions. The tradeoff is that hook and method return types become more generic. For example, callinguseSuspenseQuerywithout an expliciterrorPolicywill return a result typed as if all error policies are possible, since TypeScript can't know which specific value your instance uses at runtime.Note that making a property optional (
errorPolicy?:) is equivalent to adding the TypeScript default value ("none") to the union. SoerrorPolicy?: "all" | "ignore"has the same effect on return types aserrorPolicy: "none" | "all" | "ignore", because TypeScript assumes the option could also be absent (i.e.,"none").You can also use a partial union that only lists the values you actually use. For example, if you only ever use
"all"or"ignore", declareerrorPolicy: "all" | "ignore"(required) to keep the union narrow and avoid unused values broadening your signatures unnecessarily.
@apollo/[email protected]
Patch Changes
- #13187
bb3fd9bThanks @jerelmiller! - Fix RxJS interop issue with the observable returned byWebSocketLink.
v3.14.1
Patch Changes
-
#13168
6b84ec0Thanks @jerelmiller! - Fix issue where muting a deprecation from one entrypoint would not mute the warning when checked in a different entrypoint. This caused some rogue deprecation warnings to appear in the console even though the warnings should have been muted. -
#12970
f91fab5Thanks @acemir! - Add a deprecation message for thevariableMatcheroption inMockLink. -
#13168
6b84ec0Thanks @jerelmiller! - Ensure deprecation warnings are properly silenced in React hooks when globally disabled.
@apollo/[email protected]
Patch Changes
- #13166
0537d97Thanks @jerelmiller! - Release changes in 4.1.5 and 4.1.6.
@apollo/[email protected]
Patch Changes
-
#13128
6c0b8e4Thanks @pavelivanov! - FixuseQueryhydration mismatch whenssr: falseandskip: trueare used togetherWhen both options were combined, the server would return
loading: false(becauseuseSSRQuerychecksskipfirst), but the client'sgetServerSnapshotwas returningssrDisabledResultwithloading: true, causing a hydration mismatch.
@apollo/[email protected]
Patch Changes
-
#13155
3ba1583Thanks @jerelmiller! - Fix an issue whereuseQuerywould poll withpollIntervalwhenskipwas initialized totrue. -
#13135
fd42142Thanks @jerelmiller! - Fix issue whereclient.querywould apply options fromdefaultOptions.watchQuery.
@apollo/[email protected]
Minor Changes
- #13130
dd12231Thanks @jerelmiller! - Improve the accuracy ofclient.queryreturn type to better detect the currenterrorPolicy. Thedataproperty is no longer nullable when theerrorPolicyisnone. This makes it possible to remove theundefinedchecks or optional chaining in most cases.
@apollo/[email protected]
@apollo/[email protected]
Patch Changes
-
#13111
bf46fe0Thanks @RogerHYang! - FixcreateFetchMultipartSubscriptionto support cancellation viaAbortControllerPreviously, calling
dispose()orunsubscribe()on a subscription created bycreateFetchMultipartSubscriptionhad no effect - the underlying fetch request would continue running until completion. This was because noAbortControllerwas created or passed tofetch(), and no cleanup function was returned from the Observable.