Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect TypeScript typings for render function of FieldArray, et al #94

Open
rjgotten opened this issue Jun 30, 2023 · 0 comments
Open

Comments

@rjgotten
Copy link

rjgotten commented Jun 30, 2023

Describe the bug
The FieldArray ; FieldControl and FieldGroup components all share the same render function type definition via the GroupProps interface:

render?: (
    control: FormArray | FormControl | FormGroup
  ) => React.ReactElement<any> | React.ReactElement<any>[]

However, FieldArray will actually always use a FormArray; FieldControl will always use a FormControl; and FieldGroup will always use a FormGroup.

The use of a union type on the render function and forcing these three distinct signatures to be squished together means that when accessing any implementation-specific members such as the controls array on a FormArray, explicit type narrowing has to be added.

It's not possible to simply define the control prop in the callback to narrow the type, e..g

<FieldArray render="{( control: FormArray ) => {
  // ...
})}"/>

as this is a TS compiler error due to an incompatible type signature between the provided render function and its declared type on GroupProps. The callback needs to be able to accept anything matching the union type.

So what's left is two options:
Either add actual logic in the render function in the vein of if (control instanceof FormArray) { or hard casts in the render function body, which is purely ceremonious overhead and is, basically, noise. Because the underlying type will de facto always be the narrowed one we expect.

Or we apply type erasure with any, e.g.

<FieldArray render="{( control: any ) => {
  // ...
})}"/>

which is pretty damn bad. Because, well: it's type erasure. There goes type safety...

Expected behavior
The render function is appropriately typed with the right type of control for each of the three component types.
This could for instance be achieved by turning GroupProps into a generic interface that allows passing the expected control type, so that we get e.g.

export class FieldGroup extends React.Component<GroupProps<FormGroup>, any> {}
export class FieldArray extends React.Component<GroupProps<FormArray>, any> {}
export class FieldControl extends React.Component<GroupProps<FormControl>, any> {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant