kudlajz
kudlajz

Reputation: 1066

How to define props interface for Apollo's React HOC?

I am trying to use Apollo's React HOC to fetch and pass data to my component, but I'm getting an error of:

Argument of type 'typeof BrandList' is not assignable to parameter of type 
'CompositeComponent<{ data?: QueryProps | undefined; mutate?: MutationFunc<{}> | undefined; }>'.
Type 'typeof BrandList' is not assignable to type 'StatelessComponent<{ data?: 
QueryProps | undefined; mutate?: MutationFunc<{}> | undefined; }>'.
Type 'typeof BrandList' provides no match for the signature '(props: { data?: 
QueryProps | undefined; mutate?: MutationFunc<{}> | undefined; } & { children?: ReactNode; }, context?: any): ReactElement<any>'.

My file looks like this:

import * as React from 'react'
import {graphql} from 'react-apollo'
import gql from 'graphql-tag'

const BrandsQuery = gql`
  query {
    allBrands {
      id
      name
    }
  }
`

interface IBrand {
  id: string
  name: string
}

interface IData {
  loading: boolean,
  allBrands: IBrand[]
}

interface IProps {
  data: IData
}

class BrandList extends React.Component<IProps, void> {
  public render () {
    const {loading, allBrands} = this.props.data

    if (loading) {
      return (
        <div>Loading data..</div>
      )
    }

    return (
      <div>
        {allBrands.map((brand) => (
          <li>{brand.id} - {brand.name}</li>
        ))}
      </div>
    )
  }
}

export default graphql(BrandsQuery)(BrandList)
                                    ^^^^^^^^^

If I use {} instead of the interface, the code compiles, but then I can't use any props inside the render function.

EDIT:

I have tried to rewrite the last line to

export default graphql<any, IProps>(BrandsQuery)(BrandList)

which gets rid of the error, but now when I try to include the component as

<div>
    <BrandList />
</div>

I am getting following error:

Type '{}' is not assignable to type 'Readonly<IProps>'.
Property 'data' is missing in type '{}'.

Upvotes: 2

Views: 961

Answers (1)

kudlajz
kudlajz

Reputation: 1066

Okay, I have solved the issue like this.. I had to add another Props interface

interface IExternalProps {
  id: string
}

interface IProps extends IExternalProps {
  data: IData
}

export default graphql<any, IExternalProps}>(BrandsQuery)(BrandList)

Basically, IExternalProps is the interface for props your component expects from the outside, ie. when you actually use the component in JSX, while IProps is the interface for props you receive via GraphQL query (HOC). This interface must extend the IExternalProps, Typescript then have a chance to actually type check it.

Upvotes: 1

Related Questions