Formik validation/errors of array of objects with formik and yup

Viewed 3655

I have a form which has a grid of numbers. Each row has, say, four values, and we have several rows. In my initialValues, I set them like this:

interface Row {
  value1: number,
  value2: number,
  // ...etc
}

interface InitialValuesInterface {
  grid: Row[];
}

const initialValues: InitialValuesInterface = {
  grid: [...Array(6).keys()].map((row, index) => ({
    value1: 100,
    value2: 200,
    // ... etc
  })),
  ...otherValues
}

So we have an array of 6 objects, each object has 4 named values. In my validation, I'm asking yup to validation this part of the form like so:

const validationSchema = Yup.object().shape({
  grid: Yup.array().of(
    Yup.object().shape({
      value1: Yup.min(100, "Must be at least 100").etc(),
      value2: Yup.min(200, "Must be at least 200").etc(),
      // ...etc
    })
  )
})

In my react component, I am logging the errors for every rerender. Using formikProps = useFormikContext(), I can get formikProps.errors, and as I test these errors out, I see an errors object in the console that looks as expected:

// console.log(formikProps.errors) after triggering an error in the third row, second cell
{
  grid: Array(3)
    2:
      value2: "Must be at least 200"
}

Working as expected. However, trying to access this error in my component for error handling (I want to conditionally render an error icon with a tooltip for any given erroring cell), I am running into errors.

{formikProps.values.grid.map((row, ind) => (
  <TableCell>
    <input 
      type="number"
      name="[${ind}].value2"
      onChange={formikProps.handleChange}
    />
    {formikProps.errors.grid[ind].value2 && // <-- problem here
      <SomeErrorIconWithMessage />
    }
  </TableCell>
))}

Typescript doesn't like this at all. First it tells me that the object is possibly undefined. I cant do formikProps.errors.grid?[ind].value2 because typescript thinks I'm initiating a ternary operator, when I want the conditional check (i.e. formikProps.errors?.grid - that works fine). I try this as well (very ugly):

{formikProps.errors.grid &&
 formikProps.errors.grid[ind] &&
 formikProps.errors.grid[ind].value2 &&
   (<SomeErrorIconWithMessage />)
}

But then I get a ts error saying

Property 'value2' does not exist on type 'string | FormikErrors<Row>'.
  Property 'value2' does not exist on type 'string'.

Q Why is typescript assuming this could be a string, when my validationSchema specifically types it as an array of Row objects? Can I force typescript to treat this as Row type?

0 Answers
Related