Skip to content

Commit 2c8dfef

Browse files
authored
Merge pull request #2426 from the-guild-org/powerkiki
Improve the return type of client.query in regard of `errorPolicy`
2 parents 50009fc + cfa50ba commit 2c8dfef

6 files changed

Lines changed: 130 additions & 90 deletions

File tree

‎.changeset/lazy-lights-live.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'apollo-angular': patch
3+
---
4+
5+
`client.watchFragment()` might return null
6+
7+
This forward the reality of Apollo Client

‎.changeset/wide-carrots-dance.md‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
'apollo-angular': minor
3+
---
4+
5+
Improve the return type of client.watchFragment in regard of `errorPolicy`
6+
7+
Improves the return type of `client.query` to be smarter about the
8+
applied `errorPolicy`. The `data` and `error` properties now better
9+
reflect the expected runtime value for a given `errorPolicy`.
10+
11+
This allows the removal of `undefined` checks or optional chaining for
12+
most uses of `client.query`.
13+
14+
> [!NOTE]
15+
> The `ApolloClient.QueryResult` type is used in several places
16+
throughout the code base, most of which do not know the underlying
17+
`errorPolicy` applied (e.g. `refetchQueries`, which might have a mix of
18+
`ObservableQuery` instances with different error policies). As such, I
19+
left a fallback case that leaves the type as-is. You need to be explicit
20+
about an error policy in order to get the smarter types.
21+
22+
See equivalent in Apollo Client: https://github.com/apollographql/apollo-client/pull/13130

‎packages/apollo-angular/src/apollo.ts‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Observable } from 'rxjs';
22
import { Inject, Injectable, NgZone, Optional } from '@angular/core';
33
import type { OperationVariables } from '@apollo/client';
4-
import { ApolloClient } from '@apollo/client';
4+
import { ApolloClient, ErrorPolicy } from '@apollo/client';
55
import { QueryRef } from './query-ref';
66
import { APOLLO_FLAGS, APOLLO_NAMED_OPTIONS, APOLLO_OPTIONS } from './tokens';
77
import type { EmptyObject, Flags, NamedOptions } from './types';
@@ -18,7 +18,10 @@ export declare namespace Apollo {
1818
TVariables extends OperationVariables = EmptyObject,
1919
> = ApolloClient.QueryOptions<TData, TVariables>;
2020

21-
export type QueryResult<TData = unknown> = ApolloClient.QueryResult<TData>;
21+
export type QueryResult<
22+
TData = unknown,
23+
TErrorPolicy extends ErrorPolicy | undefined = undefined,
24+
> = ApolloClient.QueryResult<TData, TErrorPolicy>;
2225

2326
export type MutateOptions<
2427
TData = unknown,
@@ -97,7 +100,7 @@ export class ApolloBase {
97100
TVariables extends OperationVariables = EmptyObject,
98101
>(
99102
options: Apollo.WatchFragmentOptions<TFragmentData, TVariables>,
100-
): Observable<Apollo.WatchFragmentResult<TFragmentData>> {
103+
): Observable<Apollo.WatchFragmentResult<TFragmentData | null>> {
101104
const { useZone, ...opts } = options;
102105
const obs = this.ensureClient().watchFragment<TFragmentData, TVariables>({ ...opts });
103106

‎packages/apollo-angular/src/only-complete-data.ts‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ type CompleteFragment<TData> = {
77
} & GetDataState<TData, 'complete'>;
88

99
type ForWatchFragment<TData> = OperatorFunction<
10-
ApolloClient.WatchFragmentResult<TData>,
11-
CompleteFragment<TData>
10+
ApolloClient.WatchFragmentResult<TData | null>,
11+
ApolloClient.WatchFragmentResult<TData | null> & CompleteFragment<NonNullable<TData>>
1212
>;
1313

1414
/**
@@ -54,5 +54,10 @@ export const onlyComplete = onlyCompleteData;
5454
* Same as `onlyCompleteData()` but for `Apollo.watchFragment()`.
5555
*/
5656
export function onlyCompleteFragment<TData>(): ForWatchFragment<TData> {
57-
return filter((result): result is CompleteFragment<TData> => result.dataState === 'complete');
57+
return filter(
58+
(
59+
result,
60+
): result is ApolloClient.WatchFragmentResult<TData | null> &
61+
CompleteFragment<NonNullable<TData>> => result.dataState === 'complete',
62+
);
5863
}

‎packages/demo/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"@angular/core": "^20.3.0",
1818
"@angular/platform-browser": "^20.3.0",
1919
"@angular/router": "^20.3.0",
20-
"@apollo/client": "4.0.1",
20+
"@apollo/client": "^4.2.7",
2121
"apollo-angular": "workspace:*",
2222
"typescript": "~5.8.0"
2323
}

0 commit comments

Comments
 (0)