Skip to content

Conversation

@jerelmiller
Copy link
Member

@jerelmiller jerelmiller commented Apr 10, 2025

Followup to #12539 (comment)

Make it easier to type-narrow an error type by adding static is methods to each error type. This is a bit more robust than just using instanceof since that might fail due to e.g. multiple versions of Apollo Client installed.

@jerelmiller jerelmiller requested a review from phryneas April 10, 2025 22:35
@svc-apollo-docs
Copy link

svc-apollo-docs commented Apr 10, 2025

⚠️ Docs preview not attached to branch

The preview was not built because the PR's base branch release-4.0 is not in the list of sources.

An Apollo team member can comment one of the following commands to dictate which branch to attach the preview to:

  • !docs set-base-branch version-2.6
  • !docs set-base-branch main

Build ID: b4d01c490531d0d804e8b28c

@pkg-pr-new
Copy link

pkg-pr-new bot commented Apr 10, 2025

npm i https://pkg.pr.new/@apollo/client@12546

commit: 88e2954

@netlify
Copy link

netlify bot commented Apr 10, 2025

Deploy Preview for apollo-client-docs ready!

Name Link
🔨 Latest commit e4bb1e8
🔍 Latest deploy log https://app.netlify.com/sites/apollo-client-docs/deploys/680117d0dabede0008198655
😎 Deploy Preview https://deploy-preview-12546--apollo-client-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@github-actions
Copy link
Contributor

github-actions bot commented Apr 10, 2025

size-limit report 📦

Path Size
import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client" (CJS) 42.09 KB (+0.3% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client" (production) (CJS) 37.71 KB (+0.44% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client" 32.25 KB (+0.35% 🔺)
import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client" (production) 27.3 KB (+0.4% 🔺)
import { ApolloProvider } from "@apollo/client/react" 5.12 KB (0%)
import { ApolloProvider } from "@apollo/client/react" (production) 962 B (0%)
import { useQuery } from "@apollo/client/react" 10.82 KB (0%)
import { useQuery } from "@apollo/client/react" (production) 6.61 KB (0%)
import { useLazyQuery } from "@apollo/client/react" 6.3 KB (0%)
import { useLazyQuery } from "@apollo/client/react" (production) 2.13 KB (0%)
import { useMutation } from "@apollo/client/react" 5.71 KB (0%)
import { useMutation } from "@apollo/client/react" (production) 1.53 KB (0%)
import { useSubscription } from "@apollo/client/react" 6.01 KB (0%)
import { useSubscription } from "@apollo/client/react" (production) 1.83 KB (0%)
import { useSuspenseQuery } from "@apollo/client/react" 7.77 KB (0%)
import { useSuspenseQuery } from "@apollo/client/react" (production) 3.57 KB (0%)
import { useBackgroundQuery } from "@apollo/client/react" 7.57 KB (0%)
import { useBackgroundQuery } from "@apollo/client/react" (production) 3.42 KB (0%)
import { useLoadableQuery } from "@apollo/client/react" 7.59 KB (0%)
import { useLoadableQuery } from "@apollo/client/react" (production) 3.44 KB (0%)
import { useReadQuery } from "@apollo/client/react" 5.79 KB (0%)
import { useReadQuery } from "@apollo/client/react" (production) 1.62 KB (0%)
import { useFragment } from "@apollo/client/react" 5.84 KB (0%)
import { useFragment } from "@apollo/client/react" (production) 1.68 KB (0%)

/** Determine if an error is a `CombinedGraphQLErrors` instance */
static is(error: unknown): error is CombinedGraphQLErrors {
return (
error instanceof CombinedGraphQLErrors ||
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figure its best to try instanceof first since its harder to spoof. If that fails for whatever reason (multiple versions of the library for example), then we use the lower fidelity check on error.name to see if it matches.

Copy link
Member

@phryneas phryneas Apr 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the thought, but "harder to spoof" doesn't seem like a valid argument here: if someone were to spoof it, they could just set the name and the next check would still succeed - no matter if we optionally check for instanceof first or not.

If we want to prevent spoofing, we could use the mechanism that Error.isErrorand Array.isArray use:
Create a property with a well-known symbol key and check for that. (The native solutions use a [[ErrorData]] internal engine slot for that, which we obviously cannot do.)

Really not sure if that's worth it, though, and it might make serialization harder.

As it is right now, I believe the instanceof would only be beneficial if someone had a valid CombinedGraphQLErrors instance, but changed the value of name manually - and I'm not sure if we should waste bundle size on supporting that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check Symbol.for('apollo.error') property and compare name

Copy link
Member

@phryneas phryneas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting this as "Request Changes" so we don't forget discussing the instanceof check.

@changeset-bot
Copy link

changeset-bot bot commented Apr 11, 2025

🦋 Changeset detected

Latest commit: e4bb1e8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@apollo/client Minor

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

const unconventionalError = new UnconventionalError(Symbol());

test("CombinedGraphQLErrors.is", () => {
expect(CombinedGraphQLErrors.is(graphQLErrors)).toBe(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to test this with structuredClone to simulate an error from another realm, but we are polyfilling structuredClone with JSON.parse/JSON.stringify here so that won't work.

@jerelmiller jerelmiller merged commit 5dffbbe into release-4.0 Apr 17, 2025
37 checks passed
@jerelmiller jerelmiller deleted the jerel/is-helpers branch April 17, 2025 15:08
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 18, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants