Vue: Add enum sugar for prop validators

Created on 16 Mar 2018  ·  10Comments  ·  Source: vuejs/vue

What problem does this feature solve?

For enum props, it's common to validate the given value against valid enum values like this:

props: {
  position: {
    type: String,
    validator (val) {
      return ['top', 'right', 'bottom', 'left'].includes(val)
    }
  }
}

What does the proposed API look like?

I think it'll be handy to provide extra convenience by supporting this:

props: {
  position: {
    type: String,
    validator: ['top', 'right', 'bottom', 'left']
  }
}

Most helpful comment

if you want a shorthand, just use an arrow function:

props: {
  position: {
    type: String,
    validator: (val) => ['top', 'right', 'bottom', 'left'].includes(val)
  }
}

Less magic. It's Just JavaScript.

All 10 comments

if you want a shorthand, just use an arrow function:

props: {
  position: {
    type: String,
    validator: (val) => ['top', 'right', 'bottom', 'left'].includes(val)
  }
}

Less magic. It's Just JavaScript.

I also think this is not necessary. As a note, prop validation is stripped off in production builds, so why not. Beware objects enum though

Less magic. It's Just JavaScript.

If you want “less magic”, maybe quite a few of Vue's current shorthand syntax would be “unnecessary”. Even in this case, type is actually a shorthand for a type checking validator. IMO this depends on whether folks think use array value for a validator is clear enough that it stands for validating enum values.

BTW. Array.prototype.includes needs to be polyfilled or we have to write [...].indexOf(val) !== -1 if we want wider browser support. Although this doesn't cost very much, it bothers quite a few developers (including myself) to repeat this every single time.

Beware objects enum though

In most cases enum values are primitive. We can just ignore object/array values or warn about this.

The implied behavior can indeed be ambiguous regarding how objects/arrays should be handled. I actually think it's better to be more explicit here...

Why not just:

props: {
  position: {
    type: [Number, 'top', 'right', 'bottom', 'left']
  }
}

This also feels a little bit like typescript :)

@backbone87, that seems confusing and conflicts directly with the existing Vue interpretation of the type field.

I just don't think this is a common enough problem to merit a solution in the core. You can easily create your own helper to do this for you:

const onlyValues = (values) => (str) => values.indexOf(str) !== -1

const props = {
    position: {
        type: String,
        validator: onlyValues(["top", "left", "bottom", "right"])
    }
}

Also, validators don't run in Production anyway, so this is just a development helper.

@dkushner how does it conflict? the type field currently does not allow primitives, only constructors.

How about this?

props: {
  position: {
    type: String,
    in: ['top', 'right', 'bottom', 'left']
  }
}

not conflict with type field, just add a in field

If the goal is enum, maybe we should be explicit about it?

props: {
  position: {
    type: String,
    enum: ['top', 'right', 'bottom', 'left']
  }
}

It would only checks exact matches against the passed array. In example from graphQL https://graphql.org/learn/schema/#enumeration-types . From the docs it states two of the benefits.

  • Validate that any arguments of this type are one of the allowed values
  • Communicate through the type system that a field will always be one of a finite set of values

I think in this case, both apply to Vue, no?

Was this page helpful?
0 / 5 - 0 ratings