gcanti / io-ts-types

A collection of codecs and combinators for use with io-ts
https://gcanti.github.io/io-ts-types/
MIT License
311 stars 40 forks source link

Shortcut for withValidation #117

Open pke opened 5 years ago

pke commented 5 years ago

šŸš€ Feature request

Current Behavior

Multiple validation are somewhat verbose to write for custom types:

const Efficiency = withValidate(NumberFromString, 
  (u,c) =>
    either.chain(
      NumberFromString.validate(u,c),
      n => {
        if (n <= 0) {
          return t.failure(u, c, `${n}% is not effcient enough and will not heat water.`)
        } else if(n >= 100) {
          return t.failure(u, c, `${n}% efficiency is against the laws of physics`)
        }
        return t.success(n)
      }
    )
)

Desired Behavior

const Efficiency = withValidate(NumberFromString,
  (u,c) =>
    pipe(
      NumberFromString.validate(u,c),
      validate(n => n > 0 || `${n}% is not effcient enough and will not heat water.`)(u,c),
      validate(n => n < 100 || `${n}% efficiency is against the laws of physics`)(u,c)
    )
)

Suggested Solution

My solution with pipe and this implementation of validate

const validate = f => (u, c) => n => {
  const invalid = f(n)
  return invalid ? t.failure(u, c, invalid) : t.success(n)
}

It does not work though as pipe is complaining about incompatible args. It would also be nice to get rid of the NumberFromString.validate call, and make this somehow implicit.

Being new to FP I am lost here.

Who does this impact? Who is this for?

It would benefit advanced users I guess.

gcanti commented 5 years ago

Note that using withValidate like this raises a problem: is and decode are not coherent

console.log(Efficiency.is(-10)) // true
pke commented 5 years ago

Hmm... and what would be the solution to make this work? It should be a guard or something?

steida commented 4 years ago

@pke I would use t.intersection and show only the first error.

const NonEmptyTrimmedStringMax5 = t.intersection([
  // For 'Invalid string.' message.
  String,
  NonEmptyString,
  Trimmed,
  Max5,
]);