Search code examples
javascriptreactjstypescriptmaterial-uireact-dropzone

Argument of type x is not assignable to parameter of type 'ForwardRefRenderFunction<unknown, PropsWithoutRef<P>>'


I try to update an old react component with typescript and Mui : https://github.com/Yuvaleros/material-ui-dropzone

But I get

 error TS2345: Argument of type '(props: WithoutTheme<P>, ref: any) => Element' is not assignable to parameter of type 'ForwardRefRenderFunction<unknown, PropsWithoutRef<P>>'.
  Types of parameters 'props' and 'props' are incompatible.
    Type 'PropsWithoutRef<P>' is not assignable to type 'WithoutTheme<P>'.
      Type '{ theme?: Theme | undefined; }' is not assignable to type 'WithoutTheme<P>'.

   return forwardRef(function ComponentWithTheme(

on

import type { Theme } from "@mui/material/styles";
import { useTheme } from "@mui/material/styles";
import type { ComponentType } from "react";
import React, { forwardRef } from "react";

type WithoutTheme<P> = Omit<P, "theme">;

function withTheme<P extends { theme?: Theme }>(Component: ComponentType<P>) {
  return forwardRef(function ComponentWithTheme(
    props: WithoutTheme<P>,
    ref: any,
  ) {
    const theme = useTheme();
    const combinedProps = { ...props, theme } as P;

    return <Component ref={ref} {...combinedProps} />;
  });
}

export { withTheme };

I am new to typescript so fixing tsc issue is hard :s

Thanks


Solution

  • It seems like type mismatch between WithoutTheme<P> and PropsWithoutRef<P>

    PropsWithoutRef<P> (which is implicitly required by forwardRef) expects P to be used as is, but you're modifying it with Omit<P, "theme">,This is causing issue here. to fix this

    function withTheme<P extends { theme?: Theme }, R>(
      Component: ComponentType<P & React.RefAttributes<R>>
    ) {
      return forwardRef<unknown, WithoutTheme<P>>(function ComponentWithTheme(
        props,
        ref
      ) {
        const theme = useTheme();
         const combinedProps = { ...props, theme } as unknown as P;
    
        return <Component ref={ref} {...combinedProps} />;
      });
    }
    
    
    

    wrapped component receives correctly typed ref (R) and forwardRef properly infers both props and ref