React Apollo useQuery hook with TypeScript

Viewed 7901

I'm trying to get useQuery hook to work with TypeScript.

Here is my query

export const FETCH_LINKS = gql`
  query FetchLinks {
    feed {
      links {
        id
        createdAt
        url
        description
     }
  }
}
`;

I generated the types from GraphQL schema with graphql-codegen

export type Feed = {
  __typename?: 'Feed';
  links: Array<Link>;
  count: Scalars['Int'];
};

export type Link = {
  __typename?: 'Link';
  id: Scalars['ID'];
  createdAt: Scalars['DateTime'];
  description: Scalars['String'];
  url: Scalars['String'];
  postedBy?: Maybe<User>;
  votes: Array<Vote>;
};

In my component, I apply the type to useQuery hook

const { data, loading, error } = useQuery<Feed>(FETCH_LINKS);

The problem is that in the data variable I receive an object of the following shape:

{
feed: {
  __typename
  links
  count
  }
}

So, in order to loop through the array of links and render them on the page, I need to do data.feed.links.map() but the Feed type does not have a feed property on it and therefore, I get an error message Property 'feed' does not exist on type 'Feed' How do I rectify this inconsistency

3 Answers

If you check documentation you will see that you would need to create one more interface to represent data:

interface FetchLinksData {
  feed: Feed[];
}

In component you could use that like this:

const { data, loading, error } = useQuery<FetchLinksData>(FETCH_LINKS);
const feeds = data.feed;

You should utilize the typescript-operations plugin in addition to the typescript plugin. This way you will not only generate TS types for the GraphQL types in your schema, but you will also generate types based on the actual queries you use client-side. These additional types can then be plugged directly into the type variables used by the hooks.

Alternatively, you can also use the typescript-react-apollo plugin to generate your hooks for you.

If you don't want to use any additional plugins, you'll need to construct the appropriate types for your query and variables yourself:

interface FetchLinksData {
  feed: Feed
}
Related