Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 987
Donovan Hiland Avatar asked Jan 30 '19 23:01

Donovan Hiland


People also ask

How do I fix the argument of type string is not assignable to parameter of type never?

The error "Argument of type is not assignable to parameter of type 'never'" occurs when we declare an empty array without explicitly typing it and attempt to add elements to it. To solve the error, explicitly type the empty array, e.g. const arr: string[] = []; .

Is not assignable to type error?

The "Type 'string' is not assignable to type" TypeScript error occurs when we try to assign a value of type string to something that expects a different type, e.g. a more specific string literal type or an enum. To solve the error use a const or a type assertion.

Is any is a generic type?

While using any is certainly generic in that it will cause the function to accept any and all types for the type of arg , we actually are losing the information about what that type was when the function returns. If we passed in a number, the only information we have is that any type could be returned.

What is generic type in TypeScript?

TypeScript Generics is a tool which provides a way to create reusable components. It creates a component that can work with a variety of data types rather than a single data type. It allows users to consume these components and use their own types.


1 Answers

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} />
  ))
}
like image 78
Siraj Alam Avatar answered Sep 20 '22 22:09

Siraj Alam