sindresorhus / ow

Function argument validation for humans
https://sindresorhus.com/ow/
MIT License
3.8k stars 106 forks source link

Predicates for "not undefined" and "optional not undefined" #148

Open hastebrot opened 5 years ago

hastebrot commented 5 years ago

I tried to define a shape predicate to check the values of a node created by d3.hierarchy(). node has a data property which can be any type (e.g. undefined, null, object, string). As this property can be anything we might not need a validator for this, however I wanted to keep it in object.exactShape() for documentation purposes.

const OwNodeType = ow.object.exactShape({
  data: OwOptional,
  depth: ow.number,
  height: ow.number,
  parent: ow.any(ow.null, OwOptional),
  children: ow.any(ow.undefined, ow.array.ofType(OwOptional)),
  value: OwOptional,
})

There were different candidates for my purpose. I can use undefined instead of a ow predicate, but it could confuse when it is used for documentation. I could use ow.any() with no arguments, but it will always fail, when not at least one of the predicate arguments passed. So I came up with OwDefined and OwOptional.

const OwDefined = new OwNotPredicate("undefined")
const OwOptional = new OwNotPredicate("undefined", { optional: true })

I defined a new OwNotPredicate. As the constructor of ow.Predicate requires type to be an existing is validator when ow adds a new validator, we'll use undefined in OwDefined and OwOptional.

const OwNotPredicate = class extends ow.Predicate {
  constructor(type, options) {
    super(type, options)
    const negateValidator = validator => {
      return {
        message: (value, label) => `[NOT] ${validator.message(value, label)}`,
        validator: value => !validator.validator(value)
      }
    }
    this.context.validators[0] = negateValidator(this.context.validators[0])
  }
}

Just thought this might be useful, even when it does not fit perfectly in the API.

hastebrot commented 5 years ago

Maybe ow.not can be introduced:

ow(1, ow.not.undefined)
ow(undefined, ow.optional.not.undefined)

Then again, my usecase might be too specific. Are there any other usecases where ow.not might be useful?

Rastopyr commented 5 years ago

Hi guys,

i just create PR with not modifier: https://github.com/sindresorhus/ow/pull/158

sindresorhus commented 4 years ago

For anyone that wants to work on this, see the initial attempt and feedback in https://github.com/sindresorhus/ow/pull/158.