-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
create branded QueryRef
type without exposed properties
#11824
Conversation
🦋 Changeset detectedLatest commit: acc9ba9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
size-limit report 📦
|
✅ Deploy Preview for apollo-client-docs ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
/release:pr |
Please add a changeset via |
/release:pr |
A new release has been made for this PR. You can install it with:
|
export interface QueryReferenceBase<TData = unknown, TVariables = unknown> { | ||
/** @internal */ | ||
[QUERY_REF_BRAND]?(variables: TVariables): TData; | ||
} | ||
|
||
/** | ||
* A `QueryReference` is an opaque object returned by `useBackgroundQuery`. | ||
* A child component reading the `QueryReference` via `useReadQuery` will | ||
* suspend until the promise resolves. | ||
*/ | ||
export interface QueryReference<TData = unknown, TVariables = unknown> { | ||
export interface QueryReference<TData = unknown, TVariables = unknown> | ||
extends QueryReferenceBase<TData, TVariables> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit unhappy with a new QueryReferenceBase
type here tbh., this should be the QueryReference
type, and useBackgroundQuery
and QueryPreloader
should return two distinct types, where the toPromise
callback should only be exposed on the QueryPreloader
return value - it only makes sense there.
It's kinda breaking, but might be a consideration sooner rather than later @jerelmiller WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me take the weekend to think about this.
I'm in the same boat. If we can avoid the QueryReferenceBase
type, I would love that, but I can definitely understand why we might need it.
QueryReferenceBase
typeQueryRef
type without exposed properties
/release:pr |
A new release has been made for this PR. You can install it with:
|
/release:pr |
A new release has been made for this PR. You can install it with:
|
/release:pr |
A new release has been made for this PR. You can install it with:
|
// @public (undocumented) | ||
class InternalQueryReference<TData = unknown> { | ||
// Warning: (ae-forgotten-export) The symbol "InternalQueryReferenceOptions" needs to be exported by the entry point index.d.ts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These internal types are now no longer exposed 🎉
expectTypeOf(inferredQueryRef).toMatchTypeOf< | ||
QueryReference<VariablesCaseData, VariablesCaseVariables> | undefined | ||
>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ensuring similarity to the old QueryReference type
TData, | ||
TVariables | ||
> | null>(null); | ||
|
||
assertWrappedQueryRef(queryRef); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
additional assertion to make sure that a potential wrapper converted the QueryRef into a WrappedQueryRef correctly
@@ -27,17 +28,51 @@ type FetchMoreOptions<TData> = Parameters< | |||
|
|||
const QUERY_REFERENCE_SYMBOL: unique symbol = Symbol(); | |||
const PROMISE_SYMBOL: unique symbol = Symbol(); | |||
|
|||
declare const QUERY_REF_BRAND: unique symbol; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this exists only on type level
export interface QueryReference<TData = unknown, TVariables = unknown> { | ||
export interface QueryRef<TData = unknown, TVariables = unknown> { | ||
/** @internal */ | ||
[QUERY_REF_BRAND]?(variables: TVariables): TData; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using a function signature to capture the generics on this type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was a bit too loose for TVariables previously
* | ||
* {@inheritDoc @apollo/client!PreloadedQueryRef#toPromise:member(1)} | ||
*/ | ||
toPromise?: unknown; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is kinda breaking, but will only break when calling toPromise on this type - but otherwise it ensures that this type and QueryRef can be assigned to each other, which is more important for backwards compat.
* @internal | ||
* For usage in internal helpers only. | ||
*/ | ||
interface WrappedQueryRef<TData = unknown, TVariables = unknown> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is now a purely internal type (not even exported, thanks to assertWrappedQueryRef
), which removes type references to all kinds of internals from the api surface
Digging into that (unrelated) test failure, but already opening this for review. |
Create branded
QueryRef
type without exposed properties.This change deprecates
QueryReference
in favor of aQueryRef
type that doesn't expose any properties.This change also updates
preloadQuery
to return a newPreloadedQueryRef
type, which exposes thetoPromise
function as it does today. This means that query refs produced byuseBackgroundQuery
anduseLoadableQuery
now returnQueryRef
types that do not have access to atoPromise
function, which was never meant to be used in combination with these hooks.While we tend to avoid any types of breaking changes in patch releases as this, this change was necessary to support an upcoming version of the React Server Component integration, which needed to omit the
toPromise
function that would otherwise have broken at runtime.Note that this is a TypeScript-only change. At runtime,
toPromise
is still present on all queryRefs currently created by this package - but we strongly want to discourage you from accessing it in all cases except for thePreloadedQueryRef
use case.Migration is as simple as replacing all references to
QueryReference
withQueryRef
, so it should be possible to do this with a search & replace in most code bases: