Skip to content
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

Typings do not indicate that data can be {} in some cases #6548

Open
WIStudent opened this issue Jul 5, 2020 · 6 comments
Open

Typings do not indicate that data can be {} in some cases #6548

WIStudent opened this issue Jul 5, 2020 · 6 comments

Comments

@WIStudent
Copy link

I noticed that in some cases client.query and client.watchQuery will return data: {}

  • using client.query with fetch-policy cache-only, but cache does not contain the requested query
  • using client.watchQuery with fetch-policy cache-only or cache-and-network, but cache does not contain the requested query
  • using client.watchQuery and then removing the requested query from cache using cache.modify.

When using the schema and query below, client:codegen will create the following types:
schema.graphql

type Entry {
  id: String!
}

type Query {
  entries (search: String!): [Entry!]!
}

query.gql

query entries ($search: String!) {
  entries(search: $search) {
    id
  }
}

query.ts

export interface entries_entries {
  __typename: "Entry";
  id: string;
}

export interface entries {
  entries: entries_entries[];
}

export interface entriesVariables {
  search: string;
}

Using client.query<entries, entriesVariables> or client.watchQuery<entries, entriesVariables> the returned type indicates that the field data has the type data?: entries, but not that it could also be {}. This can lead to some unexpected behavior if the user is not aware that data will be {} in the above mentioned cases.

This could be fixed for example by changing the signature of client.watchQuery to

watchQuery<T = any, TVariables = OperationVariables>(options: WatchQueryOptions<TVariables>): ObservableQuery<T|{}, 
TVariables>;

As for client.query, it could be overloaded in a way that it returns Promise<ApolloQueryResult<T|{}>> instead of Promise<ApolloQueryResult<T>> when fetch-policy is set to cache-only.

An alternative solution would be to leave the types unchanged and return data: undefined instead of data: {}.

Versions

  System:
    OS: Linux 4.4 Ubuntu 20.04 LTS (Focal Fossa)
  Binaries:
    Node: 14.2.0
    Yarn: 1.22.4
    npm: 6.14.4
  npmPackages:
    @apollo/client: ^3.0.0-rc.10 => 3.0.0-rc.10 
    apollo: ^2.28.3 => 2.28.3
@tonnenpinguin
Copy link

Does this issue persist with the latest release?

During upgrading my own codebase I've noticed that data is now declared as possibly being undefined

@WIStudent
Copy link
Author

There were already cases where data can be undefined before version 3.0. The graphql spec itself defines that data can be omitted if for example an error occured. To better indicate that, data was set to being optional in version 3.0 I think. This is how ApolloQueryResult currently looks like:

type ApolloQueryResult<T> = {
    data?: T;
    errors?: ReadonlyArray<GraphQLError>;
    loading: boolean;
    networkStatus: NetworkStatus;
};

The issue I am describing above is that apollo client 3.0 will return data: {} in some cases where the cache is involved, which is not reflected in ApolloQueryResult. I am seeing this behavior in the latest 3.0.2 release.

@hwillson
Copy link
Member

hwillson commented May 3, 2021

This should no longer be an issue in @apollo/client@latest - let us know otherwise, thanks!

@hwillson hwillson closed this as completed May 3, 2021
@WIStudent
Copy link
Author

I am still getting data: {} with @apollo/client@3.3.16 whenever the cache does not contain the query and a fetch-policy like cache-only is used. Here is a demo project where you can observe this behaviour.

Nowadays I use Partial<> like this whenever the cache is involed to make sure that I do not forget to handle the case where data does not contain the query:

const {data} = await client.query<Partial<Entries>, EntriesVariables>({
    query: entriesQuery,
    variables,
    fetchPolicy: 'cache-only'
  });

@jantoine1
Copy link

I'm not sure if the exact same issue, but I'm running into a similar issue with v3.8.8. I'm using cache.modify to update a list in the root query. The first time through, the existingRefs is an array. The second time through the existingRefs is an object with numeric keys. My code is identical to the example found at https://www.apollographql.com/docs/react/caching/cache-interaction/#example-adding-an-item-to-a-list.

If this isn't the same issue, I'll create another issue with a reproducible repo.

@phryneas
Copy link
Member

@jantoine1 that seems like another issue, please open a new issue with a code example :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants