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

Make <FieldArray /> & FieldArrayRenderProps type-safer #3992

Open
Gnomeek opened this issue Sep 7, 2024 · 1 comment
Open

Make <FieldArray /> & FieldArrayRenderProps type-safer #3992

Gnomeek opened this issue Sep 7, 2024 · 1 comment

Comments

@Gnomeek
Copy link

Gnomeek commented Sep 7, 2024

Feature request

Hi team, I'd like to propose an improvement on <FieldArray /> or FieldArrayRenderProps to make it type-safer.

Current Behavior

Currently, we only have generic type on ArrayHelpers

export type FieldArrayRenderProps = ArrayHelpers & {
form: FormikProps<any>;
name: string;
};
export type FieldArrayConfig = {
/** Really the path to the array field to be updated */
name: string;
/** Should field array validate the form AFTER array updates/changes? */
validateOnChange?: boolean;
} & SharedRenderProps<FieldArrayRenderProps>;
export interface ArrayHelpers<T extends any[] = any[]> {

Desired Behavior

T of ArrayHelpers<T> should be inferred from FieldArrayRenderProps.

Suggested Solution

Maybe we can leverage knowledge from Get from type-fest to achieve something like:

import type {Get, Paths} from 'type-fest';
import { LiteralStringUnion } from 'type-fest/source/literal-union';
import { ToString } from 'type-fest/source/internal';

type Path<T> = LiteralStringUnion<ToString<Paths<T, {bracketNotation: false}> | Paths<T, {bracketNotation: true}>>>

export type FieldArrayRenderProps<
  Values = FormikValues,
  Name extends Path<Values> = any> = 
ArrayHelpers<Get<Values, Name> extends any[] ? Get<Values, Name> : any> & {
  form: FormikProps<Values>;
  name: Name;
};

export type FieldArrayConfig<Values = FormikValues, Name extends Path<Values> = any> = {
  /** Really the path to the array field to be updated */
  name: Name;
  /** Should field array validate the form AFTER array updates/changes? */
  validateOnChange?: boolean;
} & SharedRenderProps<FieldArrayRenderProps<Values, Name>>;
export interface ArrayHelpers<T extends any[] = any[]> {

Who does this impact? Who is this for?

A type-safer <FieldArray /> or FieldArrayRenderProps can improve the type coverage of the package and avoid lots of unsafe cases.

Corner cases

For nested object

type Values = {
  friends: string[];
  friendsObj: {
    name: string;
    friends: string[];
    friendsObj: {
      name: string;
    }[];
  }[];
};

type case3 = ArrayHelpers<Get<Values, 'friendsObj[0].friendsObj'>>
// will be ArrayHelpers<any> since `friendsObj[0].friendsObj` can be undefined.
// allow ArrayHelpers<T extends (any[] | undefined) = any[]> can be problematic
@Gnomeek Gnomeek changed the title Make <FieldArray /> type-safer Make <FieldArray /> & FieldArrayRenderProps type-safer Sep 7, 2024
@Gnomeek
Copy link
Author

Gnomeek commented Sep 7, 2024

Another idea comes to my mind. We can implement a ExtractArrayTypes<T> which extracts all types(include nested) in T that extends Array, thus:

export type FieldArrayRenderProps<
  Values extends FormikValues,
  T extends ExtractArrayTypes<Values>
> = ArrayHelpers<T> & {
  form: FormikProps<Values>;
  name: string;
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant