apollo-client icon indicating copy to clipboard operation
apollo-client copied to clipboard

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

Open WIStudent opened this issue 4 years ago • 6 comments

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

WIStudent avatar Jul 05 '20 15:07 WIStudent

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

tonnenpinguin avatar Jul 24 '20 17:07 tonnenpinguin

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.

WIStudent avatar Jul 24 '20 18:07 WIStudent

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

hwillson avatar May 03 '21 14:05 hwillson

I am still getting data: {} with @apollo/[email protected] 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'
  });

WIStudent avatar May 03 '21 15:05 WIStudent

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.

jantoine1 avatar Dec 08 '23 21:12 jantoine1

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

phryneas avatar Dec 14 '23 15:12 phryneas