Repository: vuejs/vue
Pull request: fix(props): handle misspelled keys on prop validation object

**What kind of change does this PR introduce?** (check at least one)

- [x] Bugfix

**Does this PR introduce a breaking change?** (check one)

- [ ] Yes
- [x] No

If yes, please describe the impact and migration path for existing applications:

**The PR fulfills these requirements:**

- [x] It's submitted to the `dev` branch for v2.x (or to a previous version branch), _not_ the `master` branch
- [x] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number)
- [x] All tests are passing: https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#development-setup
- [x] New/updated tests are included

**Other information:**

When using object for validating props, there are no checks about object content. This may take a long time before noticing that you forget to pass required prop, but there are no warnings with a misprint.

Fail cases:
- Typo in key name `deafult: false` or `require: true`
- Using non-english letter in key name (for example, russian)

P.S.: Will be great to add instance sections names validation, but I have no idea how to solve this (once I spent a lot of time before see that writed `component: {}` section instead `components: {}`).

Changed files:
filename: src/core/util/options.js
patch: @@ -4,6 +4,7 @@ import config from '../config'
 import { warn } from './debug'
 import { nativeWatch } from './env'
 import { set } from '../observer/index'
+import { assertPropObject } from './props'
 
 import {
   ASSET_TYPES,
@@ -293,6 +294,9 @@ function normalizeProps (options: Object, vm: ?Component) {
     for (const key in props) {
       val = props[key]
       name = camelize(key)
+      if (process.env.NODE_ENV !== 'production' && isPlainObject(val)) {
+        assertPropObject(name, val, vm)
+      }
       res[name] = isPlainObject(val)
         ? val
         : { type: val }

filename: src/core/util/props.js
patch: @@ -18,6 +18,13 @@ type PropOptions = {
   validator: ?Function
 };
 
+const propOptionsNames = [
+  'type',
+  'default',
+  'required',
+  'validator'
+]
+
 export function validateProp (
   key: string,
   propOptions: Object,
@@ -84,6 +91,24 @@ function getPropDefaultValue (vm: ?Component, prop: PropOptions, key: string): a
     : def
 }
 
+/**
+ * Assert whether a prop object keys are valid.
+ */
+export function assertPropObject (
+  propName: string,
+  prop: Object,
+  vm: ?Component
+) {
+  for (const key in prop) {
+    if (propOptionsNames.indexOf(key) === -1) {
+      warn(
+        `Invalid key "${key}" in validation rules object for prop "${propName}".`,
+        vm
+      )
+    }
+  }
+}
+
 /**
  * Assert whether a prop is valid.
  */

filename: test/unit/features/options/props.spec.js
patch: @@ -512,4 +512,21 @@ describe('Options props', () => {
       expect(`"${attr}" is a reserved attribute`).toHaveBeenWarned()
     })
   })
+
+  it('should warn about misspelled keys in prop validation object', () => {
+    new Vue({
+      template: '<test></test>',
+      components: {
+        test: {
+          template: '<div></div>',
+          props: {
+            value: { reqquired: true },
+            count: { deafult: 1 }
+          }
+        }
+      }
+    }).$mount()
+    expect(`Invalid key "reqquired" in validation rules object for prop "value".`).toHaveBeenWarned()
+    expect(`Invalid key "deafult" in validation rules object for prop "count".`).toHaveBeenWarned()
+  })
 })