Donovan Hiland
Donovan Hiland

Reputation: 1499

Why is type not assignable to generic type

I'm trying to build and type a HOC which just wraps a component in an ApolloProvider. I would like to be able to forward the ref on to the wrapped component. However, when I try and pass props along in the forwardRef component I'm getting type errors

Somewhere along my research spree I stumbled upon an answer that talked about generics being the issue.

const withProvider = function<P>(WrappedComponent: React.ComponentClass<P>) {

  type Props = P & { forwardedRef?: React.Ref<any> }

  class WithProvider extends React.Component<Props> {
    render() {
      const { forwardedRef, ...props } = this.props
      return (
        <ApolloProvider client={client}>
          <WrappedComponent {...props} ref={forwardedRef} />
        </ApolloProvider>
      )
    }
  }

  hoistNonReactStatics(WithProvider, WrappedComponent)

  return React.forwardRef((props, ref) => (
    <WithProvider {...props} forwardedRef={ref} />
  ))
}

Gives me the error:


Type '{ forwardedRef: string | ((instance: {} | null) => any) | RefObject<{}> | undefined; children?: ReactNode; }' is not assignable to type 'Readonly<Props>'

To me these should match up and the former should be assignable to the latter. The only thing I can think of is that Readonly<Props> contains a generic.

Can someone point me in the right direction?

Upvotes: 6

Views: 1610

Answers (1)

Siraj Alam
Siraj Alam

Reputation: 10085

Finally, I found the solution.

All you have to do is give the type of props (in React.forwardRef) as the type received which is P.

  return React.forwardRef((props:P, ref) => (
    <WithProvider {...props} forwardedRef={ref} />
  ));

Complete Code:

const withProvider = function<P>(WrappedComponent: React.ComponentClass<P>) {

  type Props = P & { forwardedRef?: React.Ref<any> }

  class WithProvider extends React.Component<Props> {
    render() {
      const { forwardedRef, ...props } = this.props
      return (
        <ApolloProvider client={client}>
          <WrappedComponent {...props} ref={forwardedRef} />
        </ApolloProvider>
      )
    }
  }

  hoistNonReactStatics(WithProvider, WrappedComponent)

  return React.forwardRef((props:P, ref) => (
    <WithProvider {...props} forwardedRef={ref} />
  ))
}

Upvotes: 1

Related Questions