0
votes

I've got a React-Final-Form which I want it typed with it's own types. But `children(renderRest)' is giving the following error:

Cannot invoke an expression whose type lacks a call signature. Type 'string | number | true | {} | ReactElement ReactElement Component)> | null) | (new (props: any) => Component)> | ReactNodeArray | ReactPortal | ((props: FormRenderProps) => ReactNode)' has no compatible call signatures.ts(2349)

And my code is:

import React from "react";
import styled from "styled-components";
import { Form as StateForm, FormProps } from "react-final-form";

import Box from "src/App/Components/Layout/Box";

const StyledForm = styled(Box)``;

const Form = ({ children, ...rest }: FormProps) => {
  return (
    <StateForm
      {...rest}
      render={({ handleSubmit, ...renderRest }) => (
        <StyledForm as="form" onSubmit={handleSubmit}>
          {children && children(renderRest)}
        </StyledForm>
      )}
    />
  );
};

export default React.memo(Form);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

This error "Cannot invoke an expression whose type lacks a call signature" has happened in various situations which I was able to solve. But not on this case unfortunately.

Any hints please? Thanks

1

1 Answers

1
votes

In the type definitions for react-final-form it defines children in RenderableProps (which FormProps extends) as:

export interface RenderableProps<T> {
  children?: ((props: T) => React.ReactNode) | React.ReactNode;
  component?: React.ComponentType<T> | string;
  render?: (props: T) => React.ReactNode;
}

So children is either a function that takes in props and creates a React.ReactNode or it is a React.ReactNode instance directly. In the latter case you can't use it like a function. Since it could be either TS will only let you do the things that are in common between the two. The error Cannot invoke an expression whose type lacks a call signature. is basically saying, "You are trying to use children like it is a function and that isn't allowed because I don't know for sure it is a function."

I don't know the react-final-form library well enough to say the best way to fix this. You could cast...

(children as ((props: T) => React.ReactNode))(renderRest);

...or you could add a type guard...

if (typeof children === 'function') {
  children(renderRest);
}