react-final-form-arrays icon indicating copy to clipboard operation
react-final-form-arrays copied to clipboard

Type 'FieldArrayRenderProps<any>' is missing the following properties from type 'ActionFormItemsProps': values

Open dmaklygin opened this issue 6 years ago • 4 comments

Are you submitting a bug report or a feature request?

Got the TS error when I use FieldArray with additional props

What is the current behavior?

<FieldArray name='newActionItems' component={ActionFormItems} values={values}  />

and

export interface ActionFormItemsProps {
  values: ActionFormDataInterface
}

export const ActionFormItems: FC<FieldArrayRenderProps<any> & ActionFormItemsProps> = ({fields, values}) => {
...
}

What is the expected behavior?

The TS linter should handle that code properly, but it highlights on component prop:

<FieldArray name='newActionItems' *component*={ActionFormItems} values={values}  />

Sandbox Link

Error:(99, 49) TS2322: Type 'FunctionComponent<FieldArrayRenderProps<any> & ActionFormItemsProps>' is not assignable to type 'string | ComponentClass<FieldArrayRenderProps<any>, any> | FunctionComponent<FieldArrayRenderProps<any>> | undefined'.
  Type 'FunctionComponent<FieldArrayRenderProps<any> & ActionFormItemsProps>' is not assignable to type 'FunctionComponent<FieldArrayRenderProps<any>>'.
    Type 'FieldArrayRenderProps<any>' is not assignable to type 'FieldArrayRenderProps<any> & ActionFormItemsProps'.
      Type 'FieldArrayRenderProps<any>' is missing the following properties from type 'ActionFormItemsProps': values

What's your environment?

IOS "version": "3.0.0",

Other information

Possible solution is to update the interface definition. So, the current implementation defines component as a React.ComponentType<T> | string

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

export interface UseFieldArrayConfig extends UseFieldConfig {
  isEqual?: (a: any[], b: any[]) => boolean
}

export interface FieldArrayProps<T extends HTMLElement>
  extends UseFieldArrayConfig,
    RenderableProps<FieldArrayRenderProps<T>> {
  name: string
  [otherProp: string]: any
}

but actually, we can pass extra props to the Component. So, I suggest you to extend the interface definition by:

interface ExtraProps {
  [otherProp: string]: any
}

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

dmaklygin avatar Jul 30 '19 20:07 dmaklygin

I think you're using FieldArray wrong. When you use the component property for the FieldArray, the component will have FieldArrayRenderProps properties. Second, if you want the values, it can be accessed in form.values

perseusl avatar Oct 09 '19 02:10 perseusl

Hi everyone. I has recently started migrating to Typescript. When using Types with FieldArray component we can show the type of the values by passing value types to FIeldArrayRenderProps

<FieldArray
 name="name"
render={(props: FIeldArrayRenderProps<MyValueTypes, any>) => (<div/>)}
>

When I inspected the FIeldArrayRenderProps definition, I found it requires two type arguments

image

The first type argument is ok, but second one is strange. It is not used, but required. Or there is a chance I did not understand it correctly. If you have any comment please help me to make it clear why second type argument is required

DalerLeo avatar May 31 '20 14:05 DalerLeo

I'm having the same issue, @dmaklygin . I got around it by using the render prop instead of component, like so:

<FieldArray
  name="things"
  render={props => <ThingsComponent myCustomProp={myCustomPropValue} {...props}  />}
/>

A bit of a bummer to have to change my code to get Typescript checks to pass.

jonathan-stone avatar Jun 16 '20 07:06 jonathan-stone

I found a solution from there (I've just search over all occurence of FieldArrayRenderProps on github...)

// consummer:
<FieldArray
          name="metadata"
          label={t("data:form.metadata")}
          keyLabel={t("data:form.key")}
          valueLabel={t("data:form.value")}
          component={KeyValueInputList}
        />

// my custom compo
interface Props {
  label: string;
  keyLabel: string;
  valueLabel: string;
}
const KeyValueInputList: React.FC<
  FieldRenderProps<string> & FieldArrayRenderProps<string, HTMLInputElement> & Props
> = (props) => {

Now you can close this issue :angel:

--- Oups, sorry, it does not work ---

serut avatar Oct 27 '21 14:10 serut