From b49b269bf4f1e449190008e055f58de1d56e7a03 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 13 Sep 2023 14:19:44 +0200 Subject: [PATCH] more type fixes --- src/cache/inmemory/entityStore.ts | 6 ++- src/core/ObservableQuery.ts | 18 ++++---- src/core/QueryInfo.ts | 7 ++-- src/core/QueryManager.ts | 19 ++++++--- src/link/http/HttpLink.ts | 2 - src/link/http/iterators/reader.ts | 14 +++++-- src/link/http/serializeFetchParameter.ts | 2 +- src/react/cache/SuspenseCache.ts | 6 ++- src/react/hoc/mutation-hoc.tsx | 1 + src/react/hooks/useBackgroundQuery.ts | 6 ++- src/react/hooks/useLazyQuery.ts | 1 + src/react/hooks/useSuspenseQuery.ts | 41 +++++++++++-------- .../core/mocking/mockSubscriptionLink.ts | 2 +- src/testing/core/withConsoleSpy.ts | 3 +- src/testing/internal/profile/profile.tsx | 2 +- src/testing/matchers/ProfiledComponent.ts | 17 ++++---- src/utilities/common/mergeDeep.ts | 2 +- src/utilities/common/mergeOptions.ts | 2 +- src/utilities/observables/Observable.ts | 1 + 19 files changed, 93 insertions(+), 59 deletions(-) diff --git a/src/cache/inmemory/entityStore.ts b/src/cache/inmemory/entityStore.ts index 8c596353775..8d5edde2982 100644 --- a/src/cache/inmemory/entityStore.ts +++ b/src/cache/inmemory/entityStore.ts @@ -755,7 +755,11 @@ class Layer extends EntityStore { public getStorage(): StorageType { let p: EntityStore = this.parent; while ((p as Layer).parent) p = (p as Layer).parent; - return p.getStorage.apply(p, arguments); + return p.getStorage.apply( + p, + // @ts-expect-error + arguments + ); } } diff --git a/src/core/ObservableQuery.ts b/src/core/ObservableQuery.ts index 1421aee9cd7..03674d849aa 100644 --- a/src/core/ObservableQuery.ts +++ b/src/core/ObservableQuery.ts @@ -929,13 +929,7 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`, newNetworkStatus?: NetworkStatus ) { return this.reobserveAsConcast(newOptions, newNetworkStatus).promise.then( - (value) => { - invariant( - value, - "A Concast finished without a result. This in an Apollo Client bug, please file a bug report." - ); - return value; - } + ensureResult ); } @@ -1102,3 +1096,13 @@ function skipCacheDataFor( fetchPolicy === "standby" ); } + +export function ensureResult( + value: ApolloQueryResult | undefined +): ApolloQueryResult { + invariant( + value, + "A Concast finished without a result. This in an Apollo Client bug, please file a bug report." + ); + return value; +} diff --git a/src/core/QueryInfo.ts b/src/core/QueryInfo.ts index 4ddb60fce34..a2e9a6c46e8 100644 --- a/src/core/QueryInfo.ts +++ b/src/core/QueryInfo.ts @@ -50,6 +50,7 @@ function wrapDestructiveCacheMethod( // that matters in any conceivable practical scenario. (destructiveMethodCounts.get(cache)! + 1) % 1e15 ); + // @ts-expect-error this is just too generic to be typed correctly return original.apply(this, arguments); }; } @@ -113,7 +114,7 @@ export class QueryInfo { // NetworkStatus.loading, but also possibly fetchMore, poll, refetch, // or setVariables. networkStatus?: NetworkStatus; - observableQuery?: ObservableQuery; + observableQuery?: ObservableQuery; lastRequestId?: number; }): this { let networkStatus = query.networkStatus || NetworkStatus.loading; @@ -214,10 +215,10 @@ export class QueryInfo { } } - public readonly observableQuery: ObservableQuery | null = null; + public readonly observableQuery: ObservableQuery | null = null; private oqListener?: QueryListener; - setObservableQuery(oq: ObservableQuery | null) { + setObservableQuery(oq: ObservableQuery | null) { if (oq === this.observableQuery) return; if (this.oqListener) { diff --git a/src/core/QueryManager.ts b/src/core/QueryManager.ts index efdd3c05a92..ae5330ed72c 100644 --- a/src/core/QueryManager.ts +++ b/src/core/QueryManager.ts @@ -51,7 +51,11 @@ import type { ErrorPolicy, MutationFetchPolicy, } from "./watchQueryOptions.js"; -import { ObservableQuery, logMissingFieldErrors } from "./ObservableQuery.js"; +import { + ObservableQuery, + ensureResult, + logMissingFieldErrors, +} from "./ObservableQuery.js"; import { NetworkStatus, isNetworkRequestInFlight } from "./networkStatus.js"; import type { ApolloQueryResult, @@ -479,7 +483,7 @@ export class QueryManager { const results: any[] = []; this.refetchQueries({ - updateCache: (cache: TCache) => { + updateCache: (cache) => { if (!skipCache) { cacheWrites.forEach((write) => cache.write(write)); } @@ -526,7 +530,7 @@ export class QueryManager { // either a SingleExecutionResult or the final ExecutionPatchResult, // call the update function. if (isFinalResult) { - update(cache, result, { + update(cache as TCache, result, { context: mutation.context, variables: mutation.variables, }); @@ -616,8 +620,11 @@ export class QueryManager { options: WatchQueryOptions, networkStatus?: NetworkStatus ): Promise> { - return this.fetchConcastWithInfo(queryId, options, networkStatus).concast - .promise; + return this.fetchConcastWithInfo( + queryId, + options, + networkStatus + ).concast.promise.then(ensureResult); } public getQueryStore() { @@ -1301,7 +1308,7 @@ export class QueryManager { normalized.variables, normalized.context ) - .then(fromVariables) + .then(fromVariables as (Variables: any) => SourcesAndInfo) .then((sourcesWithInfo) => sourcesWithInfo.sources) ); // there is just no way we can synchronously get the *right* value here, diff --git a/src/link/http/HttpLink.ts b/src/link/http/HttpLink.ts index 06479e050f2..c59c04566cf 100644 --- a/src/link/http/HttpLink.ts +++ b/src/link/http/HttpLink.ts @@ -1,10 +1,8 @@ -import type { RequestHandler } from "../core/index.js"; import { ApolloLink } from "../core/index.js"; import type { HttpOptions } from "./selectHttpOptionsAndBody.js"; import { createHttpLink } from "./createHttpLink.js"; export class HttpLink extends ApolloLink { - public requester: RequestHandler; constructor(public options: HttpOptions = {}) { super(createHttpLink(options).request); } diff --git a/src/link/http/iterators/reader.ts b/src/link/http/iterators/reader.ts index 3a81e37cf2a..d9feac48d07 100644 --- a/src/link/http/iterators/reader.ts +++ b/src/link/http/iterators/reader.ts @@ -6,7 +6,7 @@ import { canUseAsyncIteratorSymbol } from "../../../utilities/index.js"; interface ReaderIterator { - next(): Promise>; + next(): Promise>; [Symbol.asyncIterator]?(): AsyncIterator; } @@ -15,12 +15,20 @@ export default function readerIterator( ): AsyncIterableIterator { const iterator: ReaderIterator = { next() { - return reader.read(); + return reader.read() as Promise< + | ReadableStreamReadValueResult + // DoneResult has `value` optional, which doesn't comply with an + // `IteratorResult`, so we assert it to `T | undefined` instead + | Required> + >; }, }; if (canUseAsyncIteratorSymbol) { - iterator[Symbol.asyncIterator] = function (): AsyncIterator { + iterator[Symbol.asyncIterator] = function (): AsyncIterator< + T, + T | undefined + > { return this; }; } diff --git a/src/link/http/serializeFetchParameter.ts b/src/link/http/serializeFetchParameter.ts index 4ad2b3db2cd..5a08fe67269 100644 --- a/src/link/http/serializeFetchParameter.ts +++ b/src/link/http/serializeFetchParameter.ts @@ -9,7 +9,7 @@ export const serializeFetchParameter = (p: any, label: string) => { let serialized; try { serialized = JSON.stringify(p); - } catch (e) { + } catch (e: any) { const parseError = newInvariantError( `Network request failed. %s is not serializable: %s`, label, diff --git a/src/react/cache/SuspenseCache.ts b/src/react/cache/SuspenseCache.ts index e5f8036ecea..af883c0a52a 100644 --- a/src/react/cache/SuspenseCache.ts +++ b/src/react/cache/SuspenseCache.ts @@ -32,7 +32,9 @@ export class SuspenseCache { cacheKey: CacheKey, createObservable: () => ObservableQuery ) { - const ref = this.queryRefs.lookupArray(cacheKey); + const ref = this.queryRefs.lookupArray(cacheKey) as { + current?: InternalQueryReference; + }; if (!ref.current) { ref.current = new InternalQueryReference(createObservable(), { @@ -44,6 +46,6 @@ export class SuspenseCache { }); } - return ref.current as InternalQueryReference; + return ref.current; } } diff --git a/src/react/hoc/mutation-hoc.tsx b/src/react/hoc/mutation-hoc.tsx index a0098a0f290..7705c1eeda4 100644 --- a/src/react/hoc/mutation-hoc.tsx +++ b/src/react/hoc/mutation-hoc.tsx @@ -86,6 +86,7 @@ export function withMutation< return ( + {/* @ts-expect-error */} {( mutate: MutationFunction, { data, ...r }: MutationResult diff --git a/src/react/hooks/useBackgroundQuery.ts b/src/react/hooks/useBackgroundQuery.ts index 8e49114e7aa..cb6cf125113 100644 --- a/src/react/hooks/useBackgroundQuery.ts +++ b/src/react/hooks/useBackgroundQuery.ts @@ -1,8 +1,10 @@ import * as React from "react"; import type { DocumentNode, + FetchMoreQueryOptions, OperationVariables, TypedDocumentNode, + WatchQueryOptions, } from "../../core/index.js"; import { useApolloClient } from "./useApolloClient.js"; import { wrapQueryRef } from "../cache/QueryReference.js"; @@ -197,7 +199,7 @@ export function useBackgroundQuery< ]; const queryRef = suspenseCache.getQueryRef(cacheKey, () => - client.watchQuery(watchQueryOptions) + client.watchQuery(watchQueryOptions as WatchQueryOptions) ); const [promiseCache, setPromiseCache] = React.useState( @@ -213,7 +215,7 @@ export function useBackgroundQuery< const fetchMore: FetchMoreFunction = React.useCallback( (options) => { - const promise = queryRef.fetchMore(options); + const promise = queryRef.fetchMore(options as FetchMoreQueryOptions); setPromiseCache((promiseCache) => new Map(promiseCache).set(queryRef.key, queryRef.promise) diff --git a/src/react/hooks/useLazyQuery.ts b/src/react/hooks/useLazyQuery.ts index 535b9b4ceb2..51cddd464b1 100644 --- a/src/react/hooks/useLazyQuery.ts +++ b/src/react/hooks/useLazyQuery.ts @@ -75,6 +75,7 @@ export function useLazyQuery< // Only the first time populating execOptionsRef.current matters here. internalState.forceUpdateState(); } + // @ts-expect-error this is just too generic to type return method.apply(this, arguments); }; } diff --git a/src/react/hooks/useSuspenseQuery.ts b/src/react/hooks/useSuspenseQuery.ts index 1139b3a4984..dadd8bfc901 100644 --- a/src/react/hooks/useSuspenseQuery.ts +++ b/src/react/hooks/useSuspenseQuery.ts @@ -189,7 +189,7 @@ export function useSuspenseQuery< ]; const queryRef = suspenseCache.getQueryRef(cacheKey, () => - client.watchQuery(watchQueryOptions) + client.watchQuery(watchQueryOptions as WatchQueryOptions) ); const [promiseCache, setPromiseCache] = React.useState( @@ -236,18 +236,21 @@ export function useSuspenseQuery< const result = fetchPolicy === "standby" ? skipResult : __use(promise); - const fetchMore: FetchMoreFunction = React.useCallback( - (options) => { - const promise = queryRef.fetchMore(options); + const fetchMore: FetchMoreFunction = + React.useCallback( + (options) => { + const promise = queryRef.fetchMore( + options as WatchQueryOptions + ); - setPromiseCache((previousPromiseCache) => - new Map(previousPromiseCache).set(queryRef.key, queryRef.promise) - ); + setPromiseCache((previousPromiseCache) => + new Map(previousPromiseCache).set(queryRef.key, queryRef.promise) + ); - return promise; - }, - [queryRef] - ); + return promise; + }, + [queryRef] + ); const refetch: RefetchFunction = React.useCallback( (variables) => { @@ -262,13 +265,17 @@ export function useSuspenseQuery< [queryRef] ); - const subscribeToMore: SubscribeToMoreFunction = - React.useCallback( - (options) => queryRef.observable.subscribeToMore(options), - [queryRef] - ); + const subscribeToMore: SubscribeToMoreFunction< + TData | undefined, + TVariables + > = React.useCallback( + (options) => queryRef.observable.subscribeToMore(options), + [queryRef] + ); - return React.useMemo(() => { + return React.useMemo< + UseSuspenseQueryResult + >(() => { return { client, data: result.data, diff --git a/src/testing/core/mocking/mockSubscriptionLink.ts b/src/testing/core/mocking/mockSubscriptionLink.ts index 93e48d5ddb4..b91c86e8b68 100644 --- a/src/testing/core/mocking/mockSubscriptionLink.ts +++ b/src/testing/core/mocking/mockSubscriptionLink.ts @@ -15,7 +15,7 @@ export interface MockedSubscriptionResult { export class MockSubscriptionLink extends ApolloLink { public unsubscribers: any[] = []; public setups: any[] = []; - public operation: Operation; + public operation?: Operation; private observers: any[] = []; diff --git a/src/testing/core/withConsoleSpy.ts b/src/testing/core/withConsoleSpy.ts index 053abd3486d..e5ea0cfabbc 100644 --- a/src/testing/core/withConsoleSpy.ts +++ b/src/testing/core/withConsoleSpy.ts @@ -2,8 +2,7 @@ function wrapTestFunction( fn: (...args: any[]) => any, consoleMethodName: "log" | "warn" | "error" ) { - return function () { - const args = arguments; + return function (this: any, ...args: any[]) { const spy = jest.spyOn(console, consoleMethodName); spy.mockImplementation(() => {}); return new Promise((resolve) => { diff --git a/src/testing/internal/profile/profile.tsx b/src/testing/internal/profile/profile.tsx index 12527844566..f4abb64af0e 100644 --- a/src/testing/internal/profile/profile.tsx +++ b/src/testing/internal/profile/profile.tsx @@ -203,7 +203,7 @@ export function profile< return render; }, async takeRender(options: NextRenderOptions = {}) { - let error: { message?: string } | undefined = undefined; + let error: unknown = undefined; try { return await Profiled.peekRender({ [_stackTrace]: captureStackTrace(Profiled.takeRender), diff --git a/src/testing/matchers/ProfiledComponent.ts b/src/testing/matchers/ProfiledComponent.ts index c733d50e241..469cfe00995 100644 --- a/src/testing/matchers/ProfiledComponent.ts +++ b/src/testing/matchers/ProfiledComponent.ts @@ -6,10 +6,10 @@ import type { ProfiledHook, } from "../internal/index.js"; export const toRerender: MatcherFunction<[options?: NextRenderOptions]> = - async function ( - _profiled: ProfiledComponent | ProfiledHook, - options?: NextRenderOptions - ) { + async function (actual, options) { + const _profiled = actual as + | ProfiledComponent + | ProfiledHook; const profiled = "ProfiledComponent" in _profiled ? _profiled.ProfiledComponent @@ -42,11 +42,10 @@ const failed = {}; export const toRenderExactlyTimes: MatcherFunction< [times: number, options?: NextRenderOptions] -> = async function ( - _profiled: ProfiledComponent | ProfiledHook, - times: number, - optionsPerRender?: NextRenderOptions -) { +> = async function (actual, times, optionsPerRender) { + const _profiled = actual as + | ProfiledComponent + | ProfiledHook; const profiled = "ProfiledComponent" in _profiled ? _profiled.ProfiledComponent : _profiled; const options = { timeout: 100, ...optionsPerRender }; diff --git a/src/utilities/common/mergeDeep.ts b/src/utilities/common/mergeDeep.ts index a2171f9f023..451a7a56a20 100644 --- a/src/utilities/common/mergeDeep.ts +++ b/src/utilities/common/mergeDeep.ts @@ -72,7 +72,7 @@ const defaultReconciler: ReconcilerFunction = function ( export class DeepMerger { constructor( - private reconciler: ReconcilerFunction = defaultReconciler + private reconciler: ReconcilerFunction = defaultReconciler as any as ReconcilerFunction ) {} public merge(target: any, source: any, ...context: TContextArgs): any { diff --git a/src/utilities/common/mergeOptions.ts b/src/utilities/common/mergeOptions.ts index 9c945f904e4..fe4eb954bbf 100644 --- a/src/utilities/common/mergeOptions.ts +++ b/src/utilities/common/mergeOptions.ts @@ -10,7 +10,7 @@ import { compact } from "./compact.js"; type OptionsUnion = | WatchQueryOptions | QueryOptions - | MutationOptions; + | MutationOptions; export function mergeOptions< TDefaultOptions extends Partial>, diff --git a/src/utilities/observables/Observable.ts b/src/utilities/observables/Observable.ts index 04fd25cac30..5ee33965f30 100644 --- a/src/utilities/observables/Observable.ts +++ b/src/utilities/observables/Observable.ts @@ -17,6 +17,7 @@ export type { Observer, ObservableSubscription, Subscriber }; const { prototype } = Observable; const fakeObsSymbol = "@@observable" as keyof typeof prototype; if (!prototype[fakeObsSymbol]) { + // @ts-expect-error prototype[fakeObsSymbol] = function () { return this; };