Repository: apollographql/apollo-client

Problem statement:
[4.0] Default `TData` types in query APIs to `unknown` instead of `any`
Switching from `any` to `unknown` should provide better type safety in cases where we don't know the type of `TData`. Using `any` is largely considered a bad practice if you can avoid it.


Hints:

Patch:
diff --git a/src/cache/core/cache.ts b/src/cache/core/cache.ts
--- a/src/cache/core/cache.ts
+++ b/src/cache/core/cache.ts
@@ -106,10 +106,10 @@ export abstract class ApolloCache implements DataProxy {
 
   // required to implement
   // core API
-  public abstract read<TData = any, TVariables = any>(
+  public abstract read<TData = unknown, TVariables = OperationVariables>(
     query: Cache.ReadOptions<TVariables, TData>
   ): Unmasked<TData> | null;
-  public abstract write<TData = any, TVariables = any>(
+  public abstract write<TData = unknown, TVariables = OperationVariables>(
     write: Cache.WriteOptions<TData, TVariables>
   ): Reference | undefined;
 
@@ -124,8 +124,11 @@ export abstract class ApolloCache implements DataProxy {
    * returned if it contains at least one field that can be fulfilled from the
    * cache.
    */
-  public abstract diff<T>(query: Cache.DiffOptions): Cache.DiffResult<T>;
-  public abstract watch<TData = any, TVariables = any>(
+  public abstract diff<
+    TData = unknown,
+    TVariables extends OperationVariables = OperationVariables,
+  >(query: Cache.DiffOptions<TData, TVariables>): Cache.DiffResult<TData>;
+  public abstract watch<TData = unknown, TVariables = OperationVariables>(
     watch: Cache.WatchOptions<TData, TVariables>
   ): () => void;
 
@@ -247,10 +250,10 @@ export abstract class ApolloCache implements DataProxy {
   }
 
   // DataProxy API
-  public readQuery<QueryType, TVariables = any>(
-    options: Cache.ReadQueryOptions<QueryType, TVariables>,
+  public readQuery<TData = unknown, TVariables = OperationVariables>(
+    options: Cache.ReadQueryOptions<TData, TVariables>,
     optimistic = !!options.optimistic
-  ): Unmasked<QueryType> | null {
+  ): Unmasked<TData> | null {
     return this.read({
       ...options,
       rootId: options.id || "ROOT_QUERY",
@@ -259,7 +262,7 @@ export abstract class ApolloCache implements DataProxy {
   }
 
   /** {@inheritDoc @apollo/client!ApolloClient#watchFragment:member(1)} */
-  public watchFragment<TData = any, TVars = OperationVariables>(
+  public watchFragment<TData = unknown, TVars = OperationVariables>(
     options: WatchFragmentOptions<TData, TVars>
   ): Observable<WatchFragmentResult<TData>> {
     const {
@@ -360,10 +363,10 @@ export abstract class ApolloCache implements DataProxy {
     cache: WeakCache,
   });
 
-  public readFragment<FragmentType, TVariables = any>(
-    options: Cache.ReadFragmentOptions<FragmentType, TVariables>,
+  public readFragment<TData = unknown, TVariables = OperationVariables>(
+    options: Cache.ReadFragmentOptions<TData, TVariables>,
     optimistic = !!options.optimistic
-  ): Unmasked<FragmentType> | null {
+  ): Unmasked<TData> | null {
     return this.read({
       ...options,
       query: this.getFragmentDoc(options.fragment, options.fragmentName),
@@ -372,7 +375,7 @@ export abstract class ApolloCache implements DataProxy {
     });
   }
 
-  public writeQuery<TData = any, TVariables = any>({
+  public writeQuery<TData = unknown, TVariables = OperationVariables>({
     id,
     data,
     ...options
@@ -385,7 +388,7 @@ export abstract class ApolloCache implements DataProxy {
     );
   }
 
-  public writeFragment<TData = any, TVariables = any>({
+  public writeFragment<TData = unknown, TVariables = OperationVariables>({
     id,
     data,
     fragment,
@@ -401,7 +404,7 @@ export abstract class ApolloCache implements DataProxy {
     );
   }
 
-  public updateQuery<TData = any, TVariables = any>(
+  public updateQuery<TData = unknown, TVariables = OperationVariables>(
     options: Cache.UpdateQueryOptions<TData, TVariables>,
     update: (data: Unmasked<TData> | null) => Unmasked<TData> | null | void
   ): Unmasked<TData> | null {
@@ -416,7 +419,7 @@ export abstract class ApolloCache implements DataProxy {
     });
   }
 
-  public updateFragment<TData = any, TVariables = any>(
+  public updateFragment<TData = unknown, TVariables = OperationVariables>(
     options: Cache.UpdateFragmentOptions<TData, TVariables>,
     update: (data: Unmasked<TData> | null) => Unmasked<TData> | null | void
   ): Unmasked<TData> | null {
diff --git a/src/cache/core/types/Cache.ts b/src/cache/core/types/Cache.ts
--- a/src/cache/core/types/Cache.ts
+++ b/src/cache/core/types/Cache.ts
@@ -1,3 +1,4 @@
+import type { OperationVariables } from "@apollo/client/core";
 import type { Unmasked } from "@apollo/client/masking";
 
 import type { ApolloCache } from "../cache.js";
@@ -6,12 +7,12 @@ import type { AllFieldsModifier, Modifiers } from "./common.js";
 import { DataProxy } from "./DataProxy.js";
 
 export namespace Cache {
-  export type WatchCallback<TData = any> = (
+  export type WatchCallback<TData = unknown> = (
     diff: Cache.DiffResult<TData>,
     lastDiff?: Cache.DiffResult<TData>
   ) => void;
 
-  export interface ReadOptions<TVariables = any, TData = any>
+  export interface ReadOptions<TVariables = OperationVariables, TData = unknown>
     extends DataProxy.Query<TVariables, TData> {
     rootId?: string;
     previousResult?: any;
@@ -19,22 +20,26 @@ export namespace Cache {
     returnPartialData?: boolean;
   }
 
-  export interface WriteOptions<TResult = any, TVariables = any>
-    extends Omit<DataProxy.Query<TVariables, TResult>, "id">,
-      Omit<DataProxy.WriteOptions<TResult>, "data"> {
+  export interface WriteOptions<
+    TData = unknown,
+    TVariables = OperationVariables,
+  > extends Omit<DataProxy.Query<TVariables, TData>, "id">,
+      Omit<DataProxy.WriteOptions<TData>, "data"> {
     dataId?: string;
-    result: Unmasked<TResult>;
+    result: Unmasked<TData>;
   }
 
-  export interface DiffOptions<TData = any, TVariables = any>
+  export interface DiffOptions<TData = unknown, TVariables = OperationVariables>
     extends Omit<ReadOptions<TVariables, TData>, "rootId"> {
     // The DiffOptions interface is currently just an alias for
     // ReadOptions, though DiffOptions used to be responsible for
     // declaring the returnPartialData option.
   }
 
-  export interface WatchOptions<TData = any, TVariables = any>
-    extends DiffOptions<TData, TVariables> {
+  export interface WatchOptions<
+    TData = unknown,
+    TVariables = OperationVariables,
+  > extends DiffOptions<TData, TVariables> {
     watcher?: object;
     immediate?: boolean;
     callback: WatchCallback<TData>;
diff --git a/src/cache/core/types/DataProxy.ts b/src/cache/core/types/DataProxy.ts
--- a/src/cache/core/types/DataProxy.ts
+++ b/src/cache/core/types/DataProxy.ts
@@ -1,6 +1,7 @@
 import type { TypedDocumentNode } from "@graphql-typed-document-node/core";
 import type { DocumentNode } from "graphql"; // ignore-comment eslint-disable-line import/no-extraneous-dependencies, import/no-unresolved
 
+import type { OperationVariables } from "@apollo/client/core";
 import type { Unmasked } from "@apollo/client/masking";
 import type { DeepPartial, Reference } from "@apollo/client/utilities";
 
@@ -125,15 +126,15 @@ export namespace DataProxy {
       "data"
     > {}
 
-  export type DiffResult<T> =
+  export type DiffResult<TData> =
     | {
-        result: T;
+        result: TData;
         complete: true;
         missing?: never;
         fromOptimisticTransaction?: boolean;
       }
     | {
-        result: DeepPartial<T> | null;
+        result: DeepPartial<TData> | null;
         complete: false;
         missing?: MissingFieldError;
         fromOptimisticTransaction?: boolean;
@@ -150,25 +151,25 @@ export interface DataProxy {
   /**
    * Reads a GraphQL query from the root query id.
    */
-  readQuery<QueryType, TVariables = any>(
-    options: DataProxy.ReadQueryOptions<QueryType, TVariables>,
+  readQuery<TData = unknown, TVariables = OperationVariables>(
+    options: DataProxy.ReadQueryOptions<TData, TVariables>,
     optimistic?: boolean
-  ): Unmasked<QueryType> | null;
+  ): Unmasked<TData> | null;
 
   /**
    * Reads a GraphQL fragment from any arbitrary id. If there is more than
    * one fragment in the provided document then a `fragmentName` must be
    * provided to select the correct fragment.
    */
-  readFragment<FragmentType, TVariables = any>(
-    options: DataProxy.ReadFragmentOptions<FragmentType, TVariables>,
+  readFragment<TData = unknown, TVariables = OperationVariables>(
+    options: DataProxy.ReadFragmentOptions<TData, TVariables>,
     optimistic?: boolean
-  ): Unmasked<FragmentType> | null;
+  ): Unmasked<TData> | null;
 
   /**
    * Writes a GraphQL query to the root query id.
    */
-  writeQuery<TData = any, TVariables = any>(
+  writeQuery<TData = unknown, TVariables = OperationVariables>(
     options: DataProxy.WriteQueryOptions<TData, TVariables>
   ): Reference | undefined;
 
@@ -177,7 +178,7 @@ export interface DataProxy {
    * one fragment in the provided document then a `fragmentName` must be
    * provided to select the correct fragment.
    */
-  writeFragment<TData = any, TVariables = any>(
+  writeFragment<TData = unknown, TVariables = OperationVariables>(
     options: DataProxy.WriteFragmentOptions<TData, TVariables>
   ): Reference | undefined;
 }
diff --git a/src/cache/inmemory/inMemoryCache.ts b/src/cache/inmemory/inMemoryCache.ts
--- a/src/cache/inmemory/inMemoryCache.ts
+++ b/src/cache/inmemory/inMemoryCache.ts
@@ -47,16 +47,16 @@ export class InMemoryCache extends ApolloCache {
   private optimisticData!: EntityStore;
 
   protected config: InMemoryCacheConfig;
-  private watches = new Set<Cache.WatchOptions>();
+  private watches = new Set<Cache.WatchOptions<any, any>>();
 
   private storeReader!: StoreReader;
   private storeWriter!: StoreWriter;
   private addTypenameTransform = new DocumentTransform(addTypenameToDocument);
 
   private maybeBroadcastWatch!: OptimisticWrapperFunction<
-    [Cache.WatchOptions, BroadcastOptions?],
+    [Cache.WatchOptions<any, any>, BroadcastOptions?],
     any,
-    [Cache.WatchOptions]
+    [Cache.WatchOptions<any, any>]
   >;
 
   // Override the default value, since InMemoryCache result objects are frozen
@@ -171,13 +171,19 @@ export class InMemoryCache extends ApolloCache {
     return (optimistic ? this.optimisticData : this.data).extract();
   }
 
-  public read<T>(
-    options: Cache.ReadOptions & { returnPartialData: true }
-  ): T | DeepPartial<T> | null;
+  public read<TData = unknown>(
+    options: Cache.ReadOptions<OperationVariables, TData> & {
+      returnPartialData: true;
+    }
+  ): TData | DeepPartial<TData> | null;
 
-  public read<T>(options: Cache.ReadOptions): T | null;
+  public read<TData = unknown>(
+    options: Cache.ReadOptions<OperationVariables, TData>
+  ): TData | null;
 
-  public read<T>(options: Cache.ReadOptions): T | DeepPartial<T> | null {
+  public read<TData = unknown>(
+    options: Cache.ReadOptions<OperationVariables, TData>
+  ): TData | DeepPartial<TData> | null {
     const {
       // Since read returns data or null, without any additional metadata
       // about whether/where there might have been missing fields, the
@@ -189,7 +195,7 @@ export class InMemoryCache extends ApolloCache {
       returnPartialData = false,
     } = options;
 
-    return this.storeReader.diffQueryAgainstStore<T>({
+    return this.storeReader.diffQueryAgainstStore<TData>({
       ...options,
       store: options.optimistic ? this.optimisticData : this.data,
       config: this.config,
@@ -197,7 +203,9 @@ export class InMemoryCache extends ApolloCache {
     }).result;
   }
 
-  public write(options: Cache.WriteOptions): Reference | undefined {
+  public write<TData = unknown, TVariables = OperationVariables>(
+    options: Cache.WriteOptions<TData, TVariables>
+  ): Reference | undefined {
     try {
       ++this.txCount;
       return this.storeWriter.writeToStore(this.data, options);
@@ -239,9 +247,10 @@ export class InMemoryCache extends ApolloCache {
     }
   }
 
-  public diff<TData, TVariables extends OperationVariables = any>(
-    options: Cache.DiffOptions<TData, TVariables>
-  ): Cache.DiffResult<TData> {
+  public diff<
+    TData = unknown,
+    TVariables extends OperationVariables = OperationVariables,
+  >(options: Cache.DiffOptions<TData, TVariables>): Cache.DiffResult<TData> {
     return this.storeReader.diffQueryAgainstStore({
       ...options,
       store: options.optimistic ? this.optimisticData : this.data,
@@ -250,7 +259,7 @@ export class InMemoryCache extends ApolloCache {
     });
   }
 
-  public watch<TData = any, TVariables = any>(
+  public watch<TData = unknown, TVariables = OperationVariables>(
     watch: Cache.WatchOptions<TData, TVariables>
   ): () => void {
     if (!this.watches.size) {
diff --git a/src/cache/inmemory/types.ts b/src/cache/inmemory/types.ts
--- a/src/cache/inmemory/types.ts
+++ b/src/cache/inmemory/types.ts
@@ -1,5 +1,6 @@
 import type { DocumentNode, FieldNode } from "graphql";
 
+import type { OperationVariables } from "@apollo/client/core";
 import type {
   Reference,
   StoreObject,
@@ -157,7 +158,7 @@ export interface MergeTree {
 
 export interface ReadMergeModifyContext {
   store: NormalizedCache;
-  variables?: Record<string, any>;
+  variables?: OperationVariables;
   // A JSON.stringify-serialized version of context.variables.
   varString?: string;
 }
diff --git a/src/cache/inmemory/writeToStore.ts b/src/cache/inmemory/writeToStore.ts
--- a/src/cache/inmemory/writeToStore.ts
+++ b/src/cache/inmemory/writeToStore.ts
@@ -3,7 +3,7 @@ import { Trie } from "@wry/trie";
 import type { FieldNode, SelectionSetNode } from "graphql";
 import { Kind } from "graphql";
 
-import type { Cache } from "@apollo/client/core";
+import type { Cache, OperationVariables } from "@apollo/client/core";
 import type {
   FragmentMap,
   FragmentMapFunction,
@@ -127,9 +127,15 @@ export class StoreWriter {
     private fragments?: InMemoryCacheConfig["fragments"]
   ) {}
 
-  public writeToStore(
+  public writeToStore<TData = unknown, TVariables = OperationVariables>(
     store: NormalizedCache,
-    { query, result, dataId, variables, overwrite }: Cache.WriteOptions
+    {
+      query,
+      result,
+      dataId,
+      variables,
+      overwrite,
+    }: Cache.WriteOptions<TData, TVariables>
   ): Reference | undefined {
     const operationDefinition = getOperationDefinition(query)!;
     const merger = makeProcessedFieldsMerger();
@@ -145,7 +151,7 @@ export class StoreWriter {
       merge<T>(existing: T, incoming: T) {
         return merger.merge(existing, incoming) as T;
       },
-      variables,
+      variables: variables as OperationVariables,
       varString: canonicalStringify(variables),
       ...extractFragmentContext(query, this.fragments),
       overwrite: !!overwrite,
diff --git a/src/core/ApolloClient.ts b/src/core/ApolloClient.ts
--- a/src/core/ApolloClient.ts
+++ b/src/core/ApolloClient.ts
@@ -418,9 +418,11 @@ export class ApolloClient implements DataProxy {
    * a description of store reactivity.
    */
   public watchQuery<
-    T = any,
+    TData = unknown,
     TVariables extends OperationVariables = OperationVariables,
-  >(options: WatchQueryOptions<TVariables, T>): ObservableQuery<T, TVariables> {
+  >(
+    options: WatchQueryOptions<TVariables, TData>
+  ): ObservableQuery<TData, TVariables> {
     if (this.defaultOptions.watchQuery) {
       options = mergeOptions(this.defaultOptions.watchQuery, options);
     }
@@ -434,7 +436,7 @@ export class ApolloClient implements DataProxy {
       options = { ...options, fetchPolicy: "cache-first" };
     }
 
-    return this.queryManager.watchQuery<T, TVariables>(options);
+    return this.queryManager.watchQuery<TData, TVariables>(options);
   }
 
   /**
@@ -447,11 +449,11 @@ export class ApolloClient implements DataProxy {
    * server at all or just resolve from the cache, etc.
    */
   public query<
-    T = any,
+    TData = unknown,
     TVariables extends OperationVariables = OperationVariables,
   >(
-    options: QueryOptions<TVariables, T>
-  ): Promise<ApolloQueryResult<MaybeMasked<T>>> {
+    options: QueryOptions<TVariables, TData>
+  ): Promise<ApolloQueryResult<MaybeMasked<TData>>> {
     if (this.defaultOptions.query) {
       options = mergeOptions(this.defaultOptions.query, options);
     }
@@ -468,7 +470,7 @@ export class ApolloClient implements DataProxy {
       options = { ...options, fetchPolicy: "cache-first" };
     }
 
-    return this.queryManager.query<T, TVariables>(options);
+    return this.queryManager.query<TData, TVariables>(options);
   }
 
   /**
@@ -480,7 +482,7 @@ export class ApolloClient implements DataProxy {
    * It takes options as an object with the following keys and values:
    */
   public mutate<
-    TData = any,
+    TData = unknown,
     TVariables extends OperationVariables = OperationVariables,
     TContext extends Record<string, any> = DefaultContext,
     TCache extends ApolloCache = ApolloCache,
@@ -500,14 +502,14 @@ export class ApolloClient implements DataProxy {
    * `Observable` which either emits received data or an error.
    */
   public subscribe<
-    T = any,
+    TData = unknown,
     TVariables extends OperationVariables = OperationVariables,
   >(
-    options: SubscriptionOptions<TVariables, T>
-  ): Observable<FetchResult<MaybeMasked<T>>> {
+    options: SubscriptionOptions<TVariables, TData>
+  ): Observable<FetchResult<MaybeMasked<TData>>> {
     const id = this.queryManager.generateQueryId();
 
-    return this.queryManager.startGraphQLSubscription<T>(options).pipe(
+    return this.queryManager.startGraphQLSubscription<TData>(options).pipe(
       map((result) => ({
         ...result,
         data: this.queryManager.maskOperation({
@@ -529,11 +531,11 @@ export class ApolloClient implements DataProxy {
    * @param optimistic - Set to `true` to allow `readQuery` to return
    * optimistic results. Is `false` by default.
    */
-  public readQuery<T = any, TVariables = OperationVariables>(
-    options: DataProxy.Query<TVariables, T>,
+  public readQuery<TData = unknown, TVariables = OperationVariables>(
+    options: DataProxy.Query<TVariables, TData>,
     optimistic: boolean = false
-  ): Unmasked<T> | null {
-    return this.cache.readQuery<T, TVariables>(options, optimistic);
+  ): Unmasked<TData> | null {
+    return this.cache.readQuery<TData, TVariables>(options, optimistic);
   }
 
   /**
@@ -553,12 +555,9 @@ export class ApolloClient implements DataProxy {
    * to optimistic updates.
    */
 
-  public watchFragment<
-    TFragmentData = unknown,
-    TVariables = OperationVariables,
-  >(
-    options: WatchFragmentOptions<TFragmentData, TVariables>
-  ): Observable<WatchFragmentResult<TFragmentData>> {
+  public watchFragment<TData = unknown, TVariables = OperationVariables>(
+    options: WatchFragmentOptions<TData, TVariables>
+  ): Observable<WatchFragmentResult<TData>> {
     return this.cache.watchFragment({
       ...options,
       [Symbol.for("apollo.dataMasking")]: this.queryManager.dataMasking,
@@ -579,7 +578,7 @@ export class ApolloClient implements DataProxy {
    * @param optimistic - Set to `true` to allow `readFragment` to return
    * optimistic results. Is `false` by default.
    */
-  public readFragment<T = any, TVariables = OperationVariables>(
+  public readFragment<T = unknown, TVariables = OperationVariables>(
     options: DataProxy.Fragment<TVariables, T>,
     optimistic: boolean = false
   ): Unmasked<T> | null {
@@ -591,7 +590,7 @@ export class ApolloClient implements DataProxy {
    * the store. This method will start at the root query. To start at a
    * specific id returned by `dataIdFromObject` then use `writeFragment`.
    */
-  public writeQuery<TData = any, TVariables = OperationVariables>(
+  public writeQuery<TData = unknown, TVariables = OperationVariables>(
     options: DataProxy.WriteQueryOptions<TData, TVariables>
   ): Reference | undefined {
     const ref = this.cache.writeQuery<TData, TVariables>(options);
@@ -614,7 +613,7 @@ export class ApolloClient implements DataProxy {
    * in a document with multiple fragments then you must also specify a
    * `fragmentName`.
    */
-  public writeFragment<TData = any, TVariables = OperationVariables>(
+  public writeFragment<TData = unknown, TVariables = OperationVariables>(
     options: DataProxy.WriteFragmentOptions<TData, TVariables>
   ): Reference | undefined {
     const ref = this.cache.writeFragment<TData, TVariables>(options);
diff --git a/src/core/ObservableQuery.ts b/src/core/ObservableQuery.ts
--- a/src/core/ObservableQuery.ts
+++ b/src/core/ObservableQuery.ts
@@ -45,7 +45,7 @@ import type {
 const { assign, hasOwnProperty } = Object;
 
 export interface FetchMoreOptions<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
 > {
   updateQuery?: (
@@ -64,7 +64,7 @@ interface Last<TData, TVariables> {
 }
 
 export class ObservableQuery<
-    TData = any,
+    TData = unknown,
     TVariables extends OperationVariables = OperationVariables,
   >
   implements
diff --git a/src/core/QueryManager.ts b/src/core/QueryManager.ts
--- a/src/core/QueryManager.ts
+++ b/src/core/QueryManager.ts
@@ -309,7 +309,7 @@ export class QueryManager {
     this.broadcastQueries();
 
     return new Promise((resolve, reject) => {
-      return this.getObservableFromLink(
+      return this.getObservableFromLink<TData>(
         mutation,
         {
           ...context,
@@ -411,7 +411,7 @@ export class QueryManager {
 
   public markMutationResult<
     TData,
-    TVariables,
+    TVariables extends OperationVariables,
     TContext,
     TCache extends ApolloCache,
   >(
@@ -622,7 +622,7 @@ export class QueryManager {
 
   public markMutationOptimistic<
     TData,
-    TVariables,
+    TVariables extends OperationVariables,
     TContext,
     TCache extends ApolloCache,
   >(
@@ -1008,9 +1008,9 @@ export class QueryManager {
     this.getQuery(observableQuery.queryId).setObservableQuery(observableQuery);
   }
 
-  public startGraphQLSubscription<T = any>(
+  public startGraphQLSubscription<TData = unknown>(
     options: SubscriptionOptions
-  ): Observable<FetchResult<T>> {
+  ): Observable<FetchResult<TData>> {
     let { query, variables } = options;
     const {
       fetchPolicy,
@@ -1023,7 +1023,12 @@ export class QueryManager {
     variables = this.getVariables(query, variables);
 
     const makeObservable = (variables: OperationVariables) =>
-      this.getObservableFromLink<T>(query, context, variables, extensions).pipe(
+      this.getObservableFromLink<TData>(
+        query,
+        context,
+        variables,
+        extensions
+      ).pipe(
         map((result) => {
           if (fetchPolicy !== "no-cache") {
             // the subscription interface should handle not sending us results we no longer subscribe to.
@@ -1070,7 +1075,7 @@ export class QueryManager {
         .addExportedVariables(query, variables, context)
         .then(makeObservable);
 
-      return new Observable<FetchResult<T>>((observer) => {
+      return new Observable<FetchResult<TData>>((observer) => {
         let sub: Subscription | null = null;
         observablePromise.then(
           (observable) => (sub = observable.subscribe(observer)),
@@ -1116,7 +1121,7 @@ export class QueryManager {
     observable?: Observable<FetchResult<any>>;
   }>(false);
 
-  private getObservableFromLink<T = any>(
+  private getObservableFromLink<TData = unknown>(
     query: DocumentNode,
     context: any,
     variables?: OperationVariables,
@@ -1124,8 +1129,8 @@ export class QueryManager {
     // Prefer context.queryDeduplication if specified.
     deduplication: boolean = context?.queryDeduplication ??
       this.queryDeduplication
-  ): Observable<FetchResult<T>> {
-    let observable: Observable<FetchResult<T>> | undefined;
+  ): Observable<FetchResult<TData>> {
+    let observable: Observable<FetchResult<TData>> | undefined;
 
     const { serverQuery, clientQuery } = this.getDocumentInfo(query);
     if (serverQuery) {
@@ -1171,10 +1176,10 @@ export class QueryManager {
           );
         }
       } else {
-        observable = execute(link, operation) as Observable<FetchResult<T>>;
+        observable = execute(link, operation) as Observable<FetchResult<TData>>;
       }
     } else {
-      observable = of({ data: {} } as FetchResult<T>);
+      observable = of({ data: {} } as FetchResult<TData>);
       context = this.prepareContext(context);
     }
 
@@ -1211,7 +1216,7 @@ export class QueryManager {
     // through the link chain.
     const linkDocument = this.cache.transformForLink(options.query);
 
-    return this.getObservableFromLink(
+    return this.getObservableFromLink<TData>(
       linkDocument,
       options.context,
       options.variables
@@ -1253,7 +1258,7 @@ export class QueryManager {
         }
 
         const aqr: ApolloQueryResult<TData> = {
-          data: result.data,
+          data: result.data as TData,
           loading: false,
           networkStatus: NetworkStatus.ready,
           partial: !result.data,
diff --git a/src/core/watchQueryOptions.ts b/src/core/watchQueryOptions.ts
--- a/src/core/watchQueryOptions.ts
+++ b/src/core/watchQueryOptions.ts
@@ -55,7 +55,10 @@ export type ErrorPolicy = "none" | "ignore" | "all";
 /**
  * Query options.
  */
-export interface QueryOptions<TVariables = OperationVariables, TData = any> {
+export interface QueryOptions<
+  TVariables = OperationVariables,
+  TData = unknown,
+> {
   /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#query:member} */
   query: DocumentNode | TypedDocumentNode<TData, TVariables>;
 
@@ -86,7 +89,7 @@ export interface QueryOptions<TVariables = OperationVariables, TData = any> {
  */
 export interface WatchQueryOptions<
   TVariables extends OperationVariables = OperationVariables,
-  TData = any,
+  TData = unknown,
 > extends SharedWatchQueryOptions<TVariables, TData> {
   /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#query:member} */
   query: DocumentNode | TypedDocumentNode<TData, TVariables>;
@@ -146,7 +149,7 @@ export interface NextFetchPolicyContext<
   initialFetchPolicy: WatchQueryFetchPolicy;
 }
 
-export interface FetchMoreQueryOptions<TVariables, TData = any> {
+export interface FetchMoreQueryOptions<TVariables, TData = unknown> {
   /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#query:member} */
   query?: DocumentNode | TypedDocumentNode<TData, TVariables>;
   /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#variables:member} */
@@ -175,7 +178,7 @@ export type UpdateQueryOptions<TData, TVariables> = {
 );
 
 export interface UpdateQueryMapFn<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
 > {
   (
@@ -190,7 +193,7 @@ export interface UpdateQueryMapFn<
 }
 
 export type SubscribeToMoreUpdateQueryFn<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
   TSubscriptionData = TData,
 > = {
@@ -208,7 +211,7 @@ export type SubscribeToMoreUpdateQueryFn<
 };
 
 export interface SubscribeToMoreOptions<
-  TData = any,
+  TData = unknown,
   TSubscriptionVariables extends OperationVariables = OperationVariables,
   TSubscriptionData = TData,
   TVariables extends OperationVariables = TSubscriptionVariables,
@@ -245,7 +248,7 @@ export interface SubscribeToMoreFunction<
 
 export interface SubscriptionOptions<
   TVariables = OperationVariables,
-  TData = any,
+  TData = unknown,
 > {
   /** {@inheritDoc @apollo/client!SubscriptionOptionsDocumentation#query:member} */
   query: DocumentNode | TypedDocumentNode<TData, TVariables>;
@@ -267,7 +270,7 @@ export interface SubscriptionOptions<
 }
 
 interface MutationBaseOptions<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
   TContext = DefaultContext,
   TCache extends ApolloCache = ApolloCache,
@@ -308,7 +311,7 @@ interface MutationBaseOptions<
 }
 
 export interface MutationOptions<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
   TContext = DefaultContext,
   TCache extends ApolloCache = ApolloCache,
@@ -317,7 +320,7 @@ export interface MutationOptions<
   mutation: DocumentNode | TypedDocumentNode<TData, TVariables>;
 }
 export interface MutationSharedOptions<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
   TContext = DefaultContext,
   TCache extends ApolloCache = ApolloCache,
diff --git a/src/react/hooks/useFragment.ts b/src/react/hooks/useFragment.ts
--- a/src/react/hooks/useFragment.ts
+++ b/src/react/hooks/useFragment.ts
@@ -16,13 +16,13 @@ import { useDeepMemo, wrapHook } from "./internal/index.js";
 import { useApolloClient } from "./useApolloClient.js";
 import { useSyncExternalStore } from "./useSyncExternalStore.js";
 
-export interface UseFragmentOptions<TData, TVars>
+export interface UseFragmentOptions<TData, TVariables>
   extends Omit<
-      Cache.DiffOptions<NoInfer<TData>, NoInfer<TVars>>,
+      Cache.DiffOptions<NoInfer<TData>, NoInfer<TVariables>>,
       "id" | "query" | "optimistic" | "previousResult" | "returnPartialData"
     >,
     Omit<
-      Cache.ReadFragmentOptions<TData, TVars>,
+      Cache.ReadFragmentOptions<TData, TVariables>,
       "id" | "variables" | "returnPartialData"
     > {
   from: StoreObject | Reference | FragmentType<NoInfer<TData>> | string | null;
@@ -53,9 +53,10 @@ export type UseFragmentResult<TData> =
       missing?: MissingTree;
     };
 
-export function useFragment<TData = any, TVars = OperationVariables>(
-  options: UseFragmentOptions<TData, TVars>
-): UseFragmentResult<TData> {
+export function useFragment<
+  TData = unknown,
+  TVariables extends OperationVariables = OperationVariables,
+>(options: UseFragmentOptions<TData, TVariables>): UseFragmentResult<TData> {
   return wrapHook(
     "useFragment",
     // eslint-disable-next-line react-compiler/react-compiler
@@ -64,8 +65,8 @@ export function useFragment<TData = any, TVars = OperationVariables>(
   )(options);
 }
 
-function useFragment_<TData = any, TVars = OperationVariables>(
-  options: UseFragmentOptions<TData, TVars>
+function useFragment_<TData, TVariables extends OperationVariables>(
+  options: UseFragmentOptions<TData, TVariables>
 ): UseFragmentResult<TData> {
   const client = useApolloClient(options.client);
   const { cache } = client;
@@ -100,7 +101,7 @@ function useFragment_<TData = any, TVars = OperationVariables>(
     }
 
     const { cache } = client;
-    const diff = cache.diff<TData>({
+    const diff = cache.diff<TData, TVariables>({
       ...stableOptions,
       returnPartialData: true,
       id: from,
diff --git a/src/react/hooks/useLazyQuery.ts b/src/react/hooks/useLazyQuery.ts
--- a/src/react/hooks/useLazyQuery.ts
+++ b/src/react/hooks/useLazyQuery.ts
@@ -39,7 +39,7 @@ import { useApolloClient } from "./useApolloClient.js";
 import { useSyncExternalStore } from "./useSyncExternalStore.js";
 
 export interface LazyQueryHookOptions<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 > {
   /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#fetchPolicy:member} */
@@ -200,7 +200,7 @@ const EAGER_METHODS = [
  * @returns A tuple in the form of `[execute, result]`
  */
 export function useLazyQuery<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 >(
   query: DocumentNode | TypedDocumentNode<TData, TVariables>,
diff --git a/src/react/hooks/useMutation.ts b/src/react/hooks/useMutation.ts
--- a/src/react/hooks/useMutation.ts
+++ b/src/react/hooks/useMutation.ts
@@ -71,7 +71,7 @@ import { useApolloClient } from "./useApolloClient.js";
  * @returns A tuple in the form of `[mutate, result]`
  */
 export function useMutation<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
   TContext = DefaultContext,
   TCache extends ApolloCache = ApolloCache,
@@ -86,7 +86,9 @@ export function useMutation<
 ): MutationTuple<TData, TVariables, TContext, TCache> {
   const client = useApolloClient(options?.client);
   verifyDocumentType(mutation, DocumentType.Mutation);
-  const [result, setResult] = React.useState<Omit<MutationResult, "reset">>({
+  const [result, setResult] = React.useState<
+    Omit<MutationResult<TData>, "reset">
+  >({
     called: false,
     loading: false,
     client,
@@ -147,10 +149,7 @@ export function useMutation<
               executeOptions.onError || ref.current.options?.onError;
 
             if (error && onError) {
-              onError(
-                error,
-                clientOptions as MutationOptions<TData, OperationVariables>
-              );
+              onError(error, clientOptions);
             }
 
             if (mutationId === ref.current.mutationId) {
@@ -171,10 +170,7 @@ export function useMutation<
               executeOptions.onCompleted || ref.current.options?.onCompleted;
 
             if (!error) {
-              onCompleted?.(
-                response.data!,
-                clientOptions as MutationOptions<TData, OperationVariables>
-              );
+              onCompleted?.(response.data!, clientOptions);
             }
 
             return response;
@@ -201,10 +197,7 @@ export function useMutation<
               executeOptions.onError || ref.current.options?.onError;
 
             if (onError) {
-              onError(
-                error,
-                clientOptions as MutationOptions<TData, OperationVariables>
-              );
+              onError(error, clientOptions);
 
               // TODO(brian): why are we returning this here???
               return { data: void 0, errors: error };
diff --git a/src/react/hooks/useQuery.ts b/src/react/hooks/useQuery.ts
--- a/src/react/hooks/useQuery.ts
+++ b/src/react/hooks/useQuery.ts
@@ -111,7 +111,7 @@ interface InternalState<TData, TVariables extends OperationVariables> {
  * @returns Query result object
  */
 export function useQuery<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 >(
   query: DocumentNode | TypedDocumentNode<TData, TVariables>,
@@ -125,10 +125,7 @@ export function useQuery<
   )(query, options);
 }
 
-function useQuery_<
-  TData = any,
-  TVariables extends OperationVariables = OperationVariables,
->(
+function useQuery_<TData, TVariables extends OperationVariables>(
   query: DocumentNode | TypedDocumentNode<TData, TVariables>,
   options: QueryHookOptions<NoInfer<TData>, NoInfer<TVariables>>
 ) {
@@ -144,10 +141,7 @@ function useQuery_<
   );
 }
 
-function useInternalState<
-  TData = any,
-  TVariables extends OperationVariables = OperationVariables,
->(
+function useInternalState<TData, TVariables extends OperationVariables>(
   client: ApolloClient,
   query: DocumentNode | TypedDocumentNode<any, any>,
   options: QueryHookOptions<NoInfer<TData>, NoInfer<TVariables>>,
@@ -197,10 +191,7 @@ function useInternalState<
   return internalState;
 }
 
-function useQueryInternals<
-  TData = any,
-  TVariables extends OperationVariables = OperationVariables,
->(
+function useQueryInternals<TData, TVariables extends OperationVariables>(
   query: DocumentNode | TypedDocumentNode<TData, TVariables>,
   options: QueryHookOptions<NoInfer<TData>, NoInfer<TVariables>>
 ) {
@@ -253,8 +244,8 @@ function useQueryInternals<
 }
 
 function useObservableSubscriptionResult<
-  TData = any,
-  TVariables extends OperationVariables = OperationVariables,
+  TData,
+  TVariables extends OperationVariables,
 >(
   resultData: InternalResult<TData, TVariables>,
   observable: ObservableQuery<TData, TVariables>,
@@ -374,8 +365,8 @@ function useRegisterSSRObservable(
 // this hook is not compatible with any rules of React, and there's no good way to rewrite it.
 // it should stay a separate hook that will not be optimized by the compiler
 function useResubscribeIfNecessary<
-  TData = any,
-  TVariables extends OperationVariables = OperationVariables,
+  TData,
+  TVariables extends OperationVariables,
 >(
   /** this hook will mutate properties on `resultData` */
   resultData: InternalResult<TData, TVariables>,
@@ -417,8 +408,8 @@ function useResubscribeIfNecessary<
  * but the `observable` might differ between calls to `make`.
  */
 function createMakeWatchQueryOptions<
-  TData = any,
-  TVariables extends OperationVariables = OperationVariables,
+  TData,
+  TVariables extends OperationVariables,
 >(
   client: ApolloClient,
   query: DocumentNode | TypedDocumentNode<TData, TVariables>,
diff --git a/src/react/hooks/useSubscription.ts b/src/react/hooks/useSubscription.ts
--- a/src/react/hooks/useSubscription.ts
+++ b/src/react/hooks/useSubscription.ts
@@ -109,7 +109,7 @@ import { useSyncExternalStore } from "./useSyncExternalStore.js";
  * @returns Query result object
  */
 export function useSubscription<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 >(
   subscription: DocumentNode | TypedDocumentNode<TData, TVariables>,
@@ -317,7 +317,7 @@ export function useSubscription<
 }
 
 function createSubscription<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 >(
   client: ApolloClient,
diff --git a/src/react/internal/cache/FragmentReference.ts b/src/react/internal/cache/FragmentReference.ts
--- a/src/react/internal/cache/FragmentReference.ts
+++ b/src/react/internal/cache/FragmentReference.ts
@@ -5,7 +5,7 @@ import type {
   WatchFragmentOptions,
   WatchFragmentResult,
 } from "@apollo/client/cache";
-import type { ApolloClient } from "@apollo/client/core";
+import type { ApolloClient, OperationVariables } from "@apollo/client/core";
 import type { MaybeMasked } from "@apollo/client/masking";
 import type { PromiseWithState } from "@apollo/client/utilities";
 import {
@@ -25,7 +25,7 @@ interface FragmentReferenceOptions {
 
 export class FragmentReference<
   TData = unknown,
-  TVariables = Record<string, unknown>,
+  TVariables extends OperationVariables = OperationVariables,
 > {
   public readonly observable: Observable<WatchFragmentResult<TData>>;
   public readonly key: FragmentKey = {};
@@ -172,14 +172,14 @@ export class FragmentReference<
     );
   }
 
-  private getDiff<TData, TVariables>(
+  private getDiff<TData, TVariables extends OperationVariables>(
     client: ApolloClient,
     options: WatchFragmentOptions<TData, TVariables> & { from: string }
   ) {
     const { cache } = client;
     const { from, fragment, fragmentName } = options;
 
-    const diff = cache.diff({
+    const diff = cache.diff<TData, TVariables>({
       ...options,
       query: cache["getFragmentDoc"](fragment, fragmentName),
       returnPartialData: true,
diff --git a/src/react/internal/cache/SuspenseCache.ts b/src/react/internal/cache/SuspenseCache.ts
--- a/src/react/internal/cache/SuspenseCache.ts
+++ b/src/react/internal/cache/SuspenseCache.ts
@@ -3,6 +3,7 @@ import { Trie } from "@wry/trie";
 import type {
   ApolloClient,
   ObservableQuery,
+  OperationVariables,
   WatchFragmentOptions,
 } from "@apollo/client/core";
 
@@ -34,7 +35,7 @@ export class SuspenseCache {
     this.options = options;
   }
 
-  getQueryRef<TData = any>(
+  getQueryRef<TData = unknown>(
     cacheKey: CacheKey,
     createObservable: () => ObservableQuery<TData>
   ) {
@@ -54,7 +55,7 @@ export class SuspenseCache {
     return ref.current;
   }
 
-  getFragmentRef<TData, TVariables>(
+  getFragmentRef<TData, TVariables extends OperationVariables>(
     cacheKey: FragmentCacheKey,
     client: ApolloClient,
     options: WatchFragmentOptions<TData, TVariables> & { from: string }
diff --git a/src/react/types/types.ts b/src/react/types/types.ts
--- a/src/react/types/types.ts
+++ b/src/react/types/types.ts
@@ -50,7 +50,7 @@ export type CommonOptions<TOptions> = TOptions & {
 
 export interface BaseQueryOptions<
   TVariables extends OperationVariables = OperationVariables,
-  TData = any,
+  TData = unknown,
 > extends SharedWatchQueryOptions<TVariables, TData> {
   /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#ssr:member} */
   ssr?: boolean;
@@ -61,7 +61,7 @@ export interface BaseQueryOptions<
 }
 
 export interface QueryFunctionOptions<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 > extends BaseQueryOptions<TVariables, TData> {
   /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#skip:member} */
@@ -116,7 +116,7 @@ export interface ObservableQueryFields<
 }
 
 export interface QueryResult<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 > extends ObservableQueryFields<TData, TVariables> {
   /** {@inheritDoc @apollo/client!QueryResultDocumentation#client:member} */
@@ -138,7 +138,7 @@ export interface QueryResult<
 }
 
 export interface QueryDataOptions<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 > extends QueryFunctionOptions<TData, TVariables> {
   children?: (result: QueryResult<TData, TVariables>) => ReactTypes.ReactNode;
@@ -147,7 +147,7 @@ export interface QueryDataOptions<
 }
 
 export interface QueryHookOptions<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 > extends QueryFunctionOptions<TData, TVariables> {}
 
@@ -252,7 +252,7 @@ export type RefetchQueriesFunction = (
 ) => InternalRefetchQueriesInclude;
 
 export interface BaseMutationOptions<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
   TContext = DefaultContext,
   TCache extends ApolloCache = ApolloCache,
@@ -264,14 +264,17 @@ export interface BaseMutationOptions<
   /** {@inheritDoc @apollo/client!MutationOptionsDocumentation#onCompleted:member} */
   onCompleted?: (
     data: MaybeMasked<TData>,
-    clientOptions?: BaseMutationOptions
+    clientOptions?: BaseMutationOptions<TData, TVariables, TContext, TCache>
   ) => void;
   /** {@inheritDoc @apollo/client!MutationOptionsDocumentation#onError:member} */
-  onError?: (error: ErrorLike, clientOptions?: BaseMutationOptions) => void;
+  onError?: (
+    error: ErrorLike,
+    clientOptions?: BaseMutationOptions<TData, TVariables, TContext, TCache>
+  ) => void;
 }
 
 export interface MutationFunctionOptions<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
   TContext = DefaultContext,
   TCache extends ApolloCache = ApolloCache,
@@ -280,7 +283,7 @@ export interface MutationFunctionOptions<
   mutation?: DocumentNode | TypedDocumentNode<TData, TVariables>;
 }
 
-export interface MutationResult<TData = any> {
+export interface MutationResult<TData = unknown> {
   /** {@inheritDoc @apollo/client!MutationResultDocumentation#data:member} */
   data?: MaybeMasked<TData> | null;
   /** {@inheritDoc @apollo/client!MutationResultDocumentation#error:member} */
@@ -296,7 +299,7 @@ export interface MutationResult<TData = any> {
 }
 
 export declare type MutationFunction<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
   TContext = DefaultContext,
   TCache extends ApolloCache = ApolloCache,
@@ -305,14 +308,14 @@ export declare type MutationFunction<
 ) => Promise<FetchResult<MaybeMasked<TData>>>;
 
 export interface MutationHookOptions<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
   TContext = DefaultContext,
   TCache extends ApolloCache = ApolloCache,
 > extends BaseMutationOptions<TData, TVariables, TContext, TCache> {}
 
 export interface MutationDataOptions<
-  TData = any,
+  TData = unknown,
   TVariables = OperationVariables,
   TContext = DefaultContext,
   TCache extends ApolloCache = ApolloCache,
@@ -336,18 +339,18 @@ export type MutationTuple<
 
 /* Subscription types */
 
-export interface OnDataOptions<TData = any> {
+export interface OnDataOptions<TData = unknown> {
   client: ApolloClient;
   data: SubscriptionResult<TData>;
 }
 
-export interface OnSubscriptionDataOptions<TData = any> {
+export interface OnSubscriptionDataOptions<TData = unknown> {
   client: ApolloClient;
   subscriptionData: SubscriptionResult<TData>;
 }
 
 export interface BaseSubscriptionOptions<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 > {
   /** {@inheritDoc @apollo/client!SubscriptionOptionsDocumentation#variables:member} */
@@ -385,7 +388,10 @@ export interface BaseSubscriptionOptions<
   ignoreResults?: boolean;
 }
 
-export interface SubscriptionResult<TData = any, TVariables = any> {
+export interface SubscriptionResult<
+  TData = unknown,
+  TVariables = OperationVariables,
+> {
   /** {@inheritDoc @apollo/client!SubscriptionResultDocumentation#loading:member} */
   loading: boolean;
   /** {@inheritDoc @apollo/client!SubscriptionResultDocumentation#data:member} */
@@ -401,7 +407,7 @@ export interface SubscriptionResult<TData = any, TVariables = any> {
 }
 
 export interface SubscriptionHookOptions<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 > extends BaseSubscriptionOptions<TData, TVariables> {}
 
@@ -409,7 +415,7 @@ export interface SubscriptionHookOptions<
  * @deprecated This type is not used anymore. It will be removed in the next major version of Apollo Client
  */
 export interface SubscriptionDataOptions<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 > extends BaseSubscriptionOptions<TData, TVariables> {
   subscription: DocumentNode | TypedDocumentNode<TData, TVariables>;
diff --git a/src/utilities/types/NoInfer.ts b/src/utilities/types/NoInfer.ts
--- a/src/utilities/types/NoInfer.ts
+++ b/src/utilities/types/NoInfer.ts
@@ -6,7 +6,7 @@ This type was first suggested [in this Github discussion](https://github.com/mic
 Example usage:
 ```ts
 export function useQuery<
-  TData = any,
+  TData = unknown,
   TVariables extends OperationVariables = OperationVariables,
 >(
   query: DocumentNode | TypedDocumentNode<TData, TVariables>,


Test patch:
diff --git a/src/__tests__/ApolloClient.ts b/src/__tests__/ApolloClient.ts
--- a/src/__tests__/ApolloClient.ts
+++ b/src/__tests__/ApolloClient.ts
@@ -2785,7 +2785,7 @@ describe("ApolloClient", () => {
 
       client.setLink(newLink);
 
-      const { data } = await client.query({
+      const { data } = await client.query<any>({
         query: gql`
           {
             widgets
diff --git a/src/__tests__/client.ts b/src/__tests__/client.ts
--- a/src/__tests__/client.ts
+++ b/src/__tests__/client.ts
@@ -696,7 +696,7 @@ describe("client", () => {
       cache: new InMemoryCache(),
     });
 
-    return client.query({ query }).then((result: FormattedExecutionResult) => {
+    return client.query({ query }).then((result) => {
       expect(result.data).toEqual(data);
     });
   });
diff --git a/src/__tests__/dataMasking.ts b/src/__tests__/dataMasking.ts
--- a/src/__tests__/dataMasking.ts
+++ b/src/__tests__/dataMasking.ts
@@ -12,11 +12,12 @@ import {
   gql,
   InMemoryCache,
   NetworkStatus,
+  OperationVariables,
   Reference,
   TypedDocumentNode,
 } from "@apollo/client/core";
 import { CombinedGraphQLErrors } from "@apollo/client/errors";
-import { MaskedDocumentNode } from "@apollo/client/masking";
+import { MaskedDocumentNode, Unmasked } from "@apollo/client/masking";
 import {
   MockedResponse,
   MockLink,
@@ -5889,7 +5890,7 @@ describe("client.mutate", () => {
 });
 
 class TestCache extends ApolloCache {
-  public diff<T>(query: Cache.DiffOptions): DataProxy.DiffResult<T> {
+  public diff<T>(query: Cache.DiffOptions<T>): DataProxy.DiffResult<T> {
     return { result: null, complete: false };
   }
 
@@ -5905,9 +5906,9 @@ class TestCache extends ApolloCache {
     transaction(this);
   }
 
-  public read<T, TVariables = any>(
-    query: Cache.ReadOptions<TVariables>
-  ): T | null {
+  public read<T = unknown, TVariables = OperationVariables>(
+    query: Cache.ReadOptions<TVariables, T>
+  ): Unmasked<T> | null {
     return null;
   }
 
@@ -5921,11 +5922,13 @@ class TestCache extends ApolloCache {
     return this;
   }
 
-  public watch(watch: Cache.WatchOptions): () => void {
+  public watch<T, TVariables>(
+    watch: Cache.WatchOptions<T, TVariables>
+  ): () => void {
     return function () {};
   }
 
-  public write<TResult = any, TVariables = any>(
+  public write<TResult = unknown, TVariables = OperationVariables>(
     _: Cache.WriteOptions<TResult, TVariables>
   ): Reference | undefined {
     return;
diff --git a/src/__tests__/local-state/export.ts b/src/__tests__/local-state/export.ts
--- a/src/__tests__/local-state/export.ts
+++ b/src/__tests__/local-state/export.ts
@@ -159,7 +159,7 @@ describe("@client @export tests", () => {
 
     const { data } = await client.query({ query });
 
-    expect({ ...data }).toMatchObject({
+    expect(data).toMatchObject({
       currentAuthor: testAuthor,
       postCount: testPostCount,
     });
diff --git a/src/__tests__/local-state/general.ts b/src/__tests__/local-state/general.ts
--- a/src/__tests__/local-state/general.ts
+++ b/src/__tests__/local-state/general.ts
@@ -45,7 +45,7 @@ describe("General functionality", () => {
     });
 
     return client.query({ query }).then(({ data }) => {
-      expect({ ...data }).toMatchObject({ field: 1 });
+      expect(data).toMatchObject({ field: 1 });
     });
   });
 
@@ -95,7 +95,7 @@ describe("General functionality", () => {
     });
 
     return client.query({ query }).then(({ data }) => {
-      expect({ ...data }).toMatchObject({ field: 1 });
+      expect(data).toMatchObject({ field: 1 });
     });
   });
 
@@ -159,14 +159,14 @@ describe("General functionality", () => {
     return client
       .query({ query })
       .then(({ data }) => {
-        expect({ ...data }).toMatchObject({ field: 1 });
+        expect(data).toMatchObject({ field: 1 });
         expect(count).toBe(1);
       })
       .then(() =>
         client
           .query({ query, fetchPolicy: "network-only" })
           .then(({ data }) => {
-            expect({ ...data }).toMatchObject({ field: 1 });
+            expect(data).toMatchObject({ field: 1 });
             expect(count).toBe(2);
           })
       );
@@ -245,7 +245,7 @@ describe("Cache manipulation", () => {
 
       client
         .query({ query })
-        .then(({ data }) => expect({ ...data }).toMatchObject({ field: "yo" }));
+        .then(({ data }) => expect(data).toMatchObject({ field: "yo" }));
     }
   );
 
@@ -281,7 +281,7 @@ describe("Cache manipulation", () => {
       .mutate({ mutation })
       .then(() => client.query({ query }))
       .then(({ data }) => {
-        expect({ ...data }).toMatchObject({ field: 1 });
+        expect(data).toMatchObject({ field: 1 });
       });
   });
 
@@ -363,13 +363,13 @@ describe("Cache manipulation", () => {
     return client
       .mutate({ mutation, variables: { id: "1234" } })
       .then(({ data }) => {
-        expect({ ...data }).toEqual({
+        expect(data).toEqual({
           start: { field: "1234", __typename: "Field" },
         });
       })
       .then(() => client.query({ query }))
       .then(({ data }) => {
-        expect({ ...data }).toMatchObject({ field: "1234" });
+        expect(data).toMatchObject({ field: "1234" });
       });
   });
 
@@ -506,7 +506,7 @@ describe("Cache manipulation", () => {
       },
     });
     const stream = new ObservableStream(
-      client.watchQuery({ query, variables: { id: entityId } })
+      client.watchQuery<any>({ query, variables: { id: entityId } })
     );
 
     {
@@ -689,7 +689,7 @@ describe("Sample apps", () => {
     };
 
     client.addResolvers(resolvers);
-    const stream = new ObservableStream(client.watchQuery({ query }));
+    const stream = new ObservableStream(client.watchQuery<any>({ query }));
 
     {
       const { data } = await stream.takeNext();
@@ -1123,7 +1123,7 @@ describe("Combining client and server state/operations", () => {
       },
     });
 
-    await client.mutate({
+    await client.mutate<any>({
       mutation,
       update(proxy, { data: { updateUser } }) {
         proxy.writeQuery({
diff --git a/src/__tests__/mutationResults.ts b/src/__tests__/mutationResults.ts
--- a/src/__tests__/mutationResults.ts
+++ b/src/__tests__/mutationResults.ts
@@ -212,7 +212,7 @@ describe("mutation results", () => {
 
     await firstValueFrom(from(obsQuery));
     await client.mutate({ mutation });
-    const newResult = await client.query({ query });
+    const newResult = await client.query<any>({ query });
     expect(newResult.data.todoList.todos[0].completed).toBe(true);
   });
 
@@ -528,7 +528,7 @@ describe("mutation results", () => {
       });
 
       return client
-        .mutate({
+        .mutate<any>({
           mutation,
           update(
             cache,
@@ -606,7 +606,7 @@ describe("mutation results", () => {
       });
 
       return client
-        .mutate({
+        .mutate<any>({
           mutation,
           keepRootFields: true,
           update(
@@ -687,7 +687,7 @@ describe("mutation results", () => {
       });
 
       return client
-        .mutate({
+        .mutate<any>({
           mutation,
           fetchPolicy: "no-cache",
           update(
@@ -776,7 +776,7 @@ describe("mutation results", () => {
         },
       });
 
-      const newResult = await client.query({ query });
+      const newResult = await client.query<any>({ query });
 
       // There should be one more todo item than before
       expect(newResult.data.todoList.todos.length).toBe(4);
@@ -840,7 +840,7 @@ describe("mutation results", () => {
           },
         },
       });
-      const newResult = await client.query({ query });
+      const newResult = await client.query<any>({ query });
 
       // There should be one more todo item than before
       expect(newResult.data.todoList.todos.length).toBe(4);
@@ -1384,7 +1384,7 @@ describe("mutation results", () => {
         },
       });
 
-      const newResult = await client.query({ query });
+      const newResult = await client.query<any>({ query });
 
       // There should be one more todo item than before
       expect(newResult.data.todoList.todos.length).toBe(4);
@@ -1466,7 +1466,7 @@ describe("mutation results", () => {
           });
         },
       });
-      const newResult = await client.query({ query });
+      const newResult = await client.query<any>({ query });
 
       // There should be one more todo item than before
       expect(newResult.data.todoList.todos.length).toBe(4);
diff --git a/src/__tests__/optimistic.ts b/src/__tests__/optimistic.ts
--- a/src/__tests__/optimistic.ts
+++ b/src/__tests__/optimistic.ts
@@ -979,7 +979,7 @@ describe("optimistic mutation results", () => {
 
       await promise;
 
-      const result = await client.query({ query });
+      const result = await client.query<any>({ query });
 
       stream.unsubscribe();
 
@@ -1393,7 +1393,7 @@ describe("optimistic mutation results", () => {
 
       // wrap the QueryObservable with an rxjs observable
       const promise = lastValueFrom(
-        client.watchQuery({ query }).pipe(
+        client.watchQuery<any>({ query }).pipe(
           map((value) => value.data.todoList.todos),
           take(5),
           toArray()
@@ -1543,7 +1543,7 @@ describe("optimistic mutation results", () => {
         "Optimistically generated"
       );
       await promise;
-      const newResult = await client.query({ query });
+      const newResult = await client.query<any>({ query });
 
       stream.unsubscribe();
       // There should be one more todo item than before
@@ -1839,7 +1839,7 @@ describe("optimistic mutation results", () => {
       });
 
       const promise = lastValueFrom(
-        client.watchQuery({ query }).pipe(
+        client.watchQuery<any>({ query }).pipe(
           map((value) => value.data.todoList.todos),
           take(5),
           toArray()
@@ -1900,7 +1900,7 @@ describe("optimistic mutation results", () => {
         ),
       });
 
-      const query = gql`
+      const query: TypedDocumentNode<Data> = gql`
         query {
           items {
             text
@@ -1920,7 +1920,7 @@ describe("optimistic mutation results", () => {
       type Data = { items: Item[] };
 
       function append(cache: ApolloCache, item: Item) {
-        const data = cache.readQuery<Data>({ query });
+        const data = cache.readQuery({ query });
         cache.writeQuery({
           query,
           data: {
diff --git a/src/cache/core/__tests__/cache.ts b/src/cache/core/__tests__/cache.ts
--- a/src/cache/core/__tests__/cache.ts
+++ b/src/cache/core/__tests__/cache.ts
@@ -2,6 +2,7 @@ import { expectTypeOf } from "expect-type";
 import { gql } from "graphql-tag";
 
 import { Cache, DataProxy } from "@apollo/client/cache";
+import { OperationVariables, Unmasked } from "@apollo/client/core";
 
 import { Reference } from "../../../utilities/graphql/storeUtils.js";
 import { ApolloCache } from "../cache.js";
@@ -27,9 +28,9 @@ class TestCache extends ApolloCache {
     transaction(this);
   }
 
-  public read<T, TVariables = any>(
-    query: Cache.ReadOptions<TVariables>
-  ): T | null {
+  public read<T = unknown, TVariables = OperationVariables>(
+    query: Cache.ReadOptions<TVariables, T>
+  ): Unmasked<T> | null {
     return null;
   }
 
@@ -48,11 +49,13 @@ class TestCache extends ApolloCache {
     return this;
   }
 
-  public watch(watch: Cache.WatchOptions): () => void {
+  public watch<T = unknown, TVariables = OperationVariables>(
+    watch: Cache.WatchOptions<T, TVariables>
+  ): () => void {
     return function () {};
   }
 
-  public write<TResult = any, TVariables = any>(
+  public write<TResult = unknown, TVariables = OperationVariables>(
     _: Cache.WriteOptions<TResult, TVariables>
   ): Reference | undefined {
     return;
diff --git a/src/cache/inmemory/__tests__/cache.ts b/src/cache/inmemory/__tests__/cache.ts
--- a/src/cache/inmemory/__tests__/cache.ts
+++ b/src/cache/inmemory/__tests__/cache.ts
@@ -1403,7 +1403,7 @@ describe("Cache", () => {
         name: "Ben Newman",
       });
 
-      cache.updateFragment(
+      cache.updateFragment<any>(
         {
           id: bnId,
           fragment: usernameFragment,
diff --git a/src/cache/inmemory/__tests__/policies.ts b/src/cache/inmemory/__tests__/policies.ts
--- a/src/cache/inmemory/__tests__/policies.ts
+++ b/src/cache/inmemory/__tests__/policies.ts
@@ -5,6 +5,7 @@ import {
   ApolloClient,
   DocumentNode,
   NetworkStatus,
+  OperationVariables,
   Reference,
   StoreObject,
   TypedDocumentNode,
@@ -1194,7 +1195,10 @@ describe("type policies", function () {
         },
       };
 
-      function check<TData extends typeof data, TVars>(
+      function check<
+        TData extends typeof data,
+        TVars extends OperationVariables,
+      >(
         query: DocumentNode | TypedDocumentNode<TData, TVars>,
         variables?: TVars
       ) {
diff --git a/src/cache/inmemory/__tests__/writeToStore.ts b/src/cache/inmemory/__tests__/writeToStore.ts
--- a/src/cache/inmemory/__tests__/writeToStore.ts
+++ b/src/cache/inmemory/__tests__/writeToStore.ts
@@ -2895,7 +2895,14 @@ describe("writing to the store", () => {
       },
     });
 
-    const query = gql`
+    type Data = {
+      counter: {
+        __typename: "Counter";
+        count: number;
+      };
+    };
+
+    const query: TypedDocumentNode<Data> = gql`
       query {
         counter {
           count
@@ -2903,14 +2910,14 @@ describe("writing to the store", () => {
       }
     `;
 
-    const results: number[] = [];
+    const results: Data[] = [];
 
     const promise = new Promise<void>((resolve) => {
       cache.watch({
         query,
         optimistic: true,
         callback(diff) {
-          results.push(diff.result);
+          results.push(diff.result as Data);
           expect(diff.result).toEqual({
             counter: {
               __typename: "Counter",
diff --git a/src/core/__tests__/ObservableQuery.ts b/src/core/__tests__/ObservableQuery.ts
--- a/src/core/__tests__/ObservableQuery.ts
+++ b/src/core/__tests__/ObservableQuery.ts
@@ -3378,7 +3378,7 @@ describe("ObservableQuery", () => {
           cache,
         });
 
-        const observable = client.watchQuery(queryOptions);
+        const observable = client.watchQuery<any>(queryOptions);
         const values: any[] = [];
 
         return new Promise<any[]>((resolve, reject) => {
diff --git a/src/react/hooks/__tests__/useMutation.test.tsx b/src/react/hooks/__tests__/useMutation.test.tsx
--- a/src/react/hooks/__tests__/useMutation.test.tsx
+++ b/src/react/hooks/__tests__/useMutation.test.tsx
@@ -1294,7 +1294,7 @@ describe("useMutation Hook", () => {
         })
     );
 
-    const mutation = gql`
+    const mutation: TypedDocumentNode<any> = gql`
       mutation DoSomething {
         doSomething {
           time
@@ -2677,8 +2677,8 @@ describe("useMutation Hook", () => {
       );
 
       const Test = () => {
-        const { data } = useQuery(QUERY_1);
-        const [mutate] = useMutation(MUTATION_1, {
+        const { data } = useQuery<any>(QUERY_1);
+        const [mutate] = useMutation<any>(MUTATION_1, {
           awaitRefetchQueries: true,
           refetchQueries: [QUERY_1],
         });
@@ -2909,7 +2909,7 @@ describe("useMutation Hook", () => {
       });
 
       const { result } = renderHook(
-        () => useMutation(CREATE_TODO_MUTATION_DEFER, { update }),
+        () => useMutation<any>(CREATE_TODO_MUTATION_DEFER, { update }),
         {
           wrapper: ({ children }) => (
             <ApolloProvider client={client}>{children}</ApolloProvider>
diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx
--- a/src/react/hooks/__tests__/useQuery.test.tsx
+++ b/src/react/hooks/__tests__/useQuery.test.tsx
@@ -892,7 +892,7 @@ describe("useQuery Hook", () => {
             setName = setName1;
             return [
               useQuery(query, { variables: { name } }),
-              useMutation(mutation, {
+              useMutation<any>(mutation, {
                 update(cache, { data }) {
                   cache.writeQuery({
                     query,
@@ -4559,7 +4559,7 @@ describe("useQuery Hook", () => {
       using _disabledAct = disableActEnvironment();
       const { takeSnapshot, getCurrentSnapshot } =
         await renderHookToSnapshotStream(
-          () => useQuery(query, { variables: { limit: 2 } }),
+          () => useQuery<any>(query, { variables: { limit: 2 } }),
           { wrapper }
         );
 
@@ -4628,7 +4628,7 @@ describe("useQuery Hook", () => {
       const { takeSnapshot, getCurrentSnapshot } =
         await renderHookToSnapshotStream(
           () =>
-            useQuery(query, {
+            useQuery<any>(query, {
               variables: { limit: 2 },
               notifyOnNetworkStatusChange: true,
             }),
@@ -7263,7 +7263,7 @@ describe("useQuery Hook", () => {
       const { takeSnapshot, getCurrentSnapshot } =
         await renderHookToSnapshotStream(
           () => ({
-            mutation: useMutation(mutation, {
+            mutation: useMutation<any>(mutation, {
               optimisticResponse: { addCar: carData },
               update(cache, { data }) {
                 cache.modify({
@@ -9174,7 +9174,10 @@ describe("useQuery Hook", () => {
     // TODO: See if we can rewrite this with renderHookToSnapshotStream and
     // check output of hook to ensure its a stable object
     it("should handle a simple query", async () => {
-      const query = gql`
+      const query: TypedDocumentNode<
+        { hello: string },
+        Record<string, never>
+      > = gql`
         {
           hello
         }
@@ -9186,7 +9189,11 @@ describe("useQuery Hook", () => {
         },
       ];
 
-      const Component = ({ query }: any) => {
+      const Component = ({
+        query,
+      }: {
+        query: TypedDocumentNode<{ hello: string }, Record<string, never>>;
+      }) => {
         const [counter, setCounter] = useState(0);
         const result = useQuery(query);
 
@@ -9206,7 +9213,7 @@ describe("useQuery Hook", () => {
 
         return (
           <div>
-            {result.data.hello}
+            {result.data!.hello}
             {counter}
           </div>
         );
diff --git a/src/react/hooks/__tests__/useSuspenseQuery.test.tsx b/src/react/hooks/__tests__/useSuspenseQuery.test.tsx
--- a/src/react/hooks/__tests__/useSuspenseQuery.test.tsx
+++ b/src/react/hooks/__tests__/useSuspenseQuery.test.tsx
@@ -9270,7 +9270,7 @@ describe("useSuspenseQuery", () => {
       partial: false,
     });
 
-    cache.updateQuery({ query }, (data) => ({
+    cache.updateQuery<any>({ query }, (data) => ({
       hero: {
         ...data.hero,
         name: "C3PO",
diff --git a/src/react/ssr/__tests__/useQuery.test.tsx b/src/react/ssr/__tests__/useQuery.test.tsx
--- a/src/react/ssr/__tests__/useQuery.test.tsx
+++ b/src/react/ssr/__tests__/useQuery.test.tsx
@@ -1,11 +1,10 @@
 /** @jest-environment node */
 import type { Trie } from "@wry/trie";
-import { DocumentNode } from "graphql";
 import { gql } from "graphql-tag";
 import React from "react";
 
 import { InMemoryCache } from "@apollo/client/cache";
-import { ApolloClient } from "@apollo/client/core";
+import { ApolloClient, TypedDocumentNode } from "@apollo/client/core";
 import { ApolloProvider, getApolloContext } from "@apollo/client/react/context";
 import { useApolloClient, useQuery } from "@apollo/client/react/hooks";
 import { renderToStringWithData } from "@apollo/client/react/ssr";
@@ -13,7 +12,7 @@ import { MockedResponse, mockSingleLink } from "@apollo/client/testing";
 import { MockedProvider } from "@apollo/client/testing/react";
 
 describe("useQuery Hook SSR", () => {
-  const CAR_QUERY: DocumentNode = gql`
+  const CAR_QUERY: TypedDocumentNode<typeof CAR_RESULT_DATA> = gql`
     query {
       cars {
         make
@@ -48,7 +47,7 @@ describe("useQuery Hook SSR", () => {
       const { loading, data } = useQuery(CAR_QUERY);
       if (!loading) {
         expect(data).toEqual(CAR_RESULT_DATA);
-        const { make, model, vin } = data.cars[0];
+        const { make, model, vin } = data!.cars[0];
         return (
           <div>
             {make}, {model}, {vin}
@@ -96,7 +95,7 @@ describe("useQuery Hook SSR", () => {
       expect(loading).toBeTruthy();
 
       if (!loading) {
-        const { make } = data.cars[0];
+        const { make } = data!.cars[0];
         return <div>{make}</div>;
       }
       return null;
@@ -220,7 +219,7 @@ describe("useQuery Hook SSR", () => {
 
       if (!loading) {
         expect(data).toEqual(CAR_RESULT_DATA);
-        const { make, model, vin } = data.cars[0];
+        const { make, model, vin } = data!.cars[0];
         return (
           <div>
             {make}, {model}, {vin}
@@ -263,7 +262,7 @@ describe("useQuery Hook SSR", () => {
       },
     });
 
-    const query = gql`
+    const query: TypedDocumentNode<typeof initialData> = gql`
       query GetSearchResults {
         getSearchResults @client {
           locale
@@ -318,7 +317,7 @@ describe("useQuery Hook SSR", () => {
           getSearchResults: {
             pagination: { pageLimit },
           },
-        } = data;
+        } = data!;
         return <div>{pageLimit}</div>;
       }
       return null;
@@ -360,7 +359,7 @@ describe("useQuery Hook SSR", () => {
         React.useContext(getApolloContext()).renderPromises!["queryInfoTrie"];
       if (!loading) {
         expect(data).toEqual(CAR_RESULT_DATA);
-        const { make, model, vin } = data.cars[0];
+        const { make, model, vin } = data!.cars[0];
         return (
           <div>
             {make}, {model}, {vin}
diff --git a/src/testing/react/__tests__/MockedProvider.test.tsx b/src/testing/react/__tests__/MockedProvider.test.tsx
--- a/src/testing/react/__tests__/MockedProvider.test.tsx
+++ b/src/testing/react/__tests__/MockedProvider.test.tsx
@@ -1210,7 +1210,7 @@ describe("@client testing", () => {
     });
 
     function Component() {
-      const { loading, data } = useQuery(gql`
+      const { loading, data } = useQuery<any>(gql`
         {
           networkStatus @client {
             isOnline
@@ -1254,7 +1254,7 @@ describe("@client testing", () => {
     });
 
     function Component() {
-      const { loading, data } = useQuery(gql`
+      const { loading, data } = useQuery<any>(gql`
         {
           networkStatus @client {
             isOnline