Home > Enterprise >  Generics for object arguments
Generics for object arguments

Time:03-31

Why is there an error, while trying to use an A type function for B type one? Or how can I define a function type with unknown properties? Cause when I try to define props in type B as props: Record<string, unknown>, it gives me similar error.

type A = (props: { link: string }) => JSX.Element
type B = <T>(props: T) => JSX.Element
Type 'T' is not assignable to type '{ link: string; }'.

EDIT:

I am adding more readable code snippet:

type GenericType = <T>(props: T) => JSX.Element;

type LinkWrapperCreatorArgumentsType = {
  children: ReactNode;
  className: string;
  link: string;
}

const linkWrapperCreator = ({
    children,
    className,
    link,
}: LinkWrapperCreatorArgumentsType ) => (
    <a href={link} className={className}>
        {children}
    </a>
);

type Props = {
    linkWrapper: GenericType;
};

const Plans: React.FC<Props> = ({ linkWrapper }) => (
    <div>
       ...
    </div>
);

const PlansWrapper = () => (
  <Plans 
     linkWrapper={(props: LinkWrapperCreatorArgumentsType) => linkWrapperCreator(props)} />
)

// PlansWrapper give me an error
// Type '(props: LinkWrapperCreatorArgumentsType) => JSX.Element' is not assignable to type 'GenericType'.
  // Types of parameters 'props' and 'props' are incompatible.
    // Type 'T' is not assignable to type 'LinkWrapperCreatorArgumentsType'.
      // Type 'T' is not assignable to type '{ link: string; }'.

CodePudding user response:

Defining the method like this expects the method itself to be generic. Therefore, the compiler expects the passed method to preserve the generic type, as the actual type will be inferred on invocation only. (So calling the method determines its parameter type.)

What you are actually looking for is inferring the type of the parameters when defining the concrete method. Therefore, not your method but your type has to be generic:

type B<T> = (props: T) => JSX.Element

Which you can use like this

const b: B<{ link: string }> = (props) => <>{props.link}</>;

If you are using type B now in other artefacts (e.g. React components), you have to populate T up to the point where it gets defined:

function Component<T>({ linkWrapper }: { linkWrapper: B<T> }) { /* ... */ }

And here, the generic finally gets defined:

<Component linkWrapper={(props) => <>{props.link}</>} />
  • Related