ealush / vest

Vest ✅ Declarative validations framework

Home Page:https://vestjs.dev/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

using compose with isArrayOf throws error

alveshelio opened this issue · comments

Hi,

I have this validation

import { create, enforce, test } from 'vest'
import compose from 'vest/enforce/compose'
import { partial } from 'vest/enforce/schema'
import { useFormValidationMessages } from '@messages'
import { SelectedTechnology } from '@models'

export function useTechnologiesFormValidation() {
  const formValidationMessages = useFormValidationMessages()

  const Technology = compose(
    enforce.shape(
      partial({
        id: enforce.isString(),
        value: enforce.isString(),
        label: enforce.isString(),
        releaseYear: enforce.isString(),
        yearsOfExperience: enforce.isString(),
        warningInput: enforce.isBoolean(),
      })
    )
  )
  return create('TechnologiesForm', (data: TechnologiesFormData) => {
    test('yearsOfExperience', formValidationMessages.format('fieldRequired'), () => {
      enforce(data.yearsOfExperience).isNotBlank()
    })

    test('programmingLanguages', formValidationMessages.format('fieldRequired'), () => {
      enforce(data.programmingLanguages)
        .isArrayOf(Technology)
        .longerThanOrEquals(1)
        .shorterThanOrEquals(3)
    })
    test('frameworks', formValidationMessages.format('fieldRequired'), () => {
      enforce(data.frameworks).isArrayOf(Technology).longerThanOrEquals(1).shorterThanOrEquals(10)
    })
  })
}

But this is throwing a TypeScript error
TS2345: Argument of type 'TComposeResult' is not assignable to parameter of type 'TLazy'.
Type 'TComposeResult' is missing the following properties from type 'IRules': isArrayOf, loose, shape, optional, and 57 more.

If I define Technology like so

const Technology = compose(
    enforce.shape({
      id: enforce.optional(enforce.isString()),
      value: enforce.isString(),
      label: enforce.isString(),
      releaseYear: enforce.isString(),
      yearsOfExperience: enforce.isString(),
      warningInput: enforce.optional(enforce.isBoolean()),
    })
  )

Then I get this error
image
and I still have the TypeScript error in Technology.

I'm not sure if this is the best approach to validate an array of objects.

Also, how can I define a message for longerThanOrEquals or shorterThanOrEquals?
The validation needs to check if the object in the array has the proper shape but it also needs to validate that the number of objects must be at least 1 and no more than 3 and I'd like to have a message for these two cases too.

Hey @alveshelio, thanks for the detailed report, it really helped me debug the issue. I just tested and I can confirm this issue reproduces on my end as well. I think I found its cause, it looks like the type definition for isArrayOf was too broad and it couldn't make sense of the compose return type which was not as broad. I changed it to use the bare minimum required for a validation, and it seems to fix it on my end.

I am releasing a testing version for you to try, can you please report back if it works fine on your end as well? If it does, I will tomorrow ship it as vest@4.0.3. Here is the change to the code: https://github.com/ealush/vest/pull/774/files

Until then, here's the testing version, I hope it fixes the issue on your end as well.

npm i vest@4.0.3-dev-0bdac6

@alveshelio after some more testing, I released 4.0.3. Please let me know if that solves it for you.