diff --git a/src/core/util/options.js b/src/core/util/options.js
index 945d43c69b8..48215e2c273 100644
--- a/src/core/util/options.js
+++ b/src/core/util/options.js
@@ -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,
@@ -282,6 +283,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 }
diff --git a/src/core/util/props.js b/src/core/util/props.js
index 310514d7df6..dcc2358e46d 100644
--- a/src/core/util/props.js
+++ b/src/core/util/props.js
@@ -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.
*/
diff --git a/test/unit/features/options/props.spec.js b/test/unit/features/options/props.spec.js
index ae2baefff99..42acbe6b88b 100644
--- a/test/unit/features/options/props.spec.js
+++ b/test/unit/features/options/props.spec.js
@@ -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: '