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

Validation on the root element #104

Open
benneq opened this issue Jan 7, 2019 · 2 comments
Open

Validation on the root element #104

benneq opened this issue Jan 7, 2019 · 2 comments

Comments

@benneq
Copy link

benneq commented Jan 7, 2019

I want to validate a single (non-object) value, like this:

spected(
    [[ isNotEmpty, "must not be empty" ]],
    "foo"
);

I get the following error:

Uncaught TypeError: Invalid attempt to destructure non-iterable instance

Another use case would be something like this:

const obj = null; (or undefined, or anything else)
spected(
    [[ val => typeof val === 'object', "must be an object" ]],
    obj
)

Or maybe: Is object or array? (both are valid). And then apply validation either to the object, or to all elements of the array.

@busypeoples
Copy link
Owner

Thanks for the feedback, will try to see how we can approach this as soon as I have some time. Should find some time this week!

@benneq
Copy link
Author

benneq commented Jan 8, 2019

Thank you! :)

I guess root validation would basically just the code "within" the reduce of the validate method.

Something like this might work (pseudo code):

const validate = curry((successFn: Function, failFn: Function, spec: Object, input: Object): Object => {
  const inputFn = typeof input === 'function' ? input : (key?: string) => key ? input : input
  const input = inputFn();

  if(typeof input === 'object') {
    const keys = Object.keys(inputFn())
    return reduce((result, key) => {
      // ... just like it was before
    }
  } else {
    // here comes the code from within the `reduce` function
    // i just removed all the "key" and "...result" stuff
    // i've not tested this at all 
    const inputObj = input;
    const value = inputObj
    const predicates = spec
    if (Array.isArray(predicates)) {
      return transform(() => successFn(value), failFn, map(f => runPredicate(f, value, inputObj, key), predicates)
    } else if (typeof predicates === 'object') {
      return validate(successFn, failFn, predicates, value)
    } else if (typeof predicates === 'function') {
      const rules = predicates(value)
      return validate(successFn, failFn, rules, value)
    } else {
      return successFn([])
    }
  }
})

Btw. could you make the const inputFn line a bit better formatted? I still don't understand what it does 😆 Here's how I read it:

const inputFn = typeof input === 'function' // if input === 'function'
    ? input // then return input
    : (key?: string) => key // else if ???
    ? input // then return input
    : input // else return input

The "else if" part doesn't make sense to me. Or maybe (more likely) I'm just reading it wrong

Using this formatting, ternary operators (even nested) are really easy to read:

const res = a === null                  // if a === null
    ? 'null'                            // then return 'null'
    : typeof a === 'string'             // else if a is a string
    ? a === 'foo'                       // then check if a === 'foo'
        ? 'it is foo'                   // if that's true, return 'it is foo'
        : 'it's not foo, but a string'  // if that's not true, return this
    : 'not a string, and not null';     // else return this

// equivalent:
if(a === null) {
  return 'null'
} else if(typeof a === 'string') {
  if(a === 'foo') {
    return 'it is foo'
  } else {
    return 'it's not foo, but a string'
  }
} else {
  return 'not a string, and not null'
}

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

2 participants