diff --git a/docs/rules/no-invalid-model-keys.md b/docs/rules/no-invalid-model-keys.md
new file mode 100644
index 000000000..b69cbf952
--- /dev/null
+++ b/docs/rules/no-invalid-model-keys.md
@@ -0,0 +1,103 @@
+---
+pageClass: rule-details
+sidebarDepth: 0
+title: vue/no-invalid-model-keys
+description: require valid keys in model option
+---
+# vue/no-invalid-model-keys
+
+> require valid keys in model option
+
+
+## :book: Rule Details
+
+This rule is aimed at preventing invalid keys in model option.
+
+
+```vue
+
+```
+
+
+
+```vue
+
+```
+
+
+
+```vue
+
+```
+
+
+
+```vue
+
+```
+
+
+
+```vue
+
+```
+
+
+
+```vue
+
+```
+
+
+
+## :mag: Implementation
+
+- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-invalid-model-keys.js)
+- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-invalid-model-keys.js)
diff --git a/lib/index.js b/lib/index.js
index cc18e3055..a5f632314 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -81,6 +81,7 @@ module.exports = {
'no-empty-component-block': require('./rules/no-empty-component-block'),
'no-empty-pattern': require('./rules/no-empty-pattern'),
'no-extra-parens': require('./rules/no-extra-parens'),
+ 'no-invalid-model-keys': require('./rules/no-invalid-model-keys'),
'no-irregular-whitespace': require('./rules/no-irregular-whitespace'),
'no-lifecycle-after-await': require('./rules/no-lifecycle-after-await'),
'no-lone-template': require('./rules/no-lone-template'),
diff --git a/lib/rules/no-invalid-model-keys.js b/lib/rules/no-invalid-model-keys.js
new file mode 100644
index 000000000..3a4b7ccf6
--- /dev/null
+++ b/lib/rules/no-invalid-model-keys.js
@@ -0,0 +1,56 @@
+/**
+ * @fileoverview Requires valid keys in model option.
+ * @author Alex Sokolov
+ */
+'use strict'
+
+const utils = require('../utils')
+
+/**
+ * @typedef {import('../utils').GroupName} GroupName
+ */
+
+// ------------------------------------------------------------------------------
+// Rule Definition
+// ------------------------------------------------------------------------------
+/** @type {GroupName[]} */
+const GROUP_NAMES = ['model']
+
+const VALID_MODEL_KEYS = ['prop', 'event']
+
+module.exports = {
+ meta: {
+ type: 'problem',
+ docs: {
+ description: 'require valid keys in model option',
+ categories: undefined,
+ url: 'https://eslint.vuejs.org/rules/no-invalid-model-keys.html'
+ },
+ fixable: null,
+ schema: []
+ },
+ /** @param {RuleContext} context */
+ create(context) {
+ const groups = new Set(GROUP_NAMES)
+
+ // ----------------------------------------------------------------------
+ // Public
+ // ----------------------------------------------------------------------
+
+ return utils.executeOnVue(context, (obj) => {
+ const properties = utils.iterateProperties(obj, groups)
+
+ for (const o of properties) {
+ if (VALID_MODEL_KEYS.indexOf(o.name) === -1) {
+ context.report({
+ node: o.node,
+ message: "Invalid key '{{name}}' in model option.",
+ data: {
+ name: o.name
+ }
+ })
+ }
+ }
+ })
+ }
+}
diff --git a/tests/lib/rules/no-invalid-model-keys.js b/tests/lib/rules/no-invalid-model-keys.js
new file mode 100644
index 000000000..ebe4de973
--- /dev/null
+++ b/tests/lib/rules/no-invalid-model-keys.js
@@ -0,0 +1,151 @@
+/**
+ * @fileoverview Prevents invalid keys in model option.
+ * @author Alex Sokolov
+ */
+'use strict'
+
+// ------------------------------------------------------------------------------
+// Requirements
+// ------------------------------------------------------------------------------
+
+const rule = require('../../../lib/rules/no-invalid-model-keys')
+const RuleTester = require('eslint').RuleTester
+
+// ------------------------------------------------------------------------------
+// Tests
+// ------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester({
+ parserOptions: {
+ ecmaVersion: 2018,
+ sourceType: 'module'
+ }
+})
+ruleTester.run('no-invalid-model-keys', rule, {
+ valid: [
+ {
+ filename: 'test.vue',
+ code: `
+ export default {
+ model: {
+ prop: 'list'
+ }
+ }
+ `
+ },
+ {
+ filename: 'test.vue',
+ code: `
+ export default {
+ model: {
+ event: 'update'
+ }
+ }
+ `
+ },
+ {
+ filename: 'test.vue',
+ code: `
+ export default {
+ model: {
+ prop: 'list',
+ event: 'update'
+ }
+ }
+ `
+ }
+ ],
+
+ invalid: [
+ {
+ filename: 'test.vue',
+ code: `
+ export default {
+ model: {
+ props: 'list'
+ }
+ }
+ `,
+ errors: ["Invalid key 'props' in model option."]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+ export default {
+ model: {
+ events: 'update'
+ }
+ }
+ `,
+ errors: ["Invalid key 'events' in model option."]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+ export default {
+ model: {
+ props: 'list',
+ event: 'update'
+ }
+ }
+ `,
+ errors: ["Invalid key 'props' in model option."]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+ export default {
+ model: {
+ prop: 'list',
+ events: 'update'
+ }
+ }
+ `,
+ errors: ["Invalid key 'events' in model option."]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+ export default {
+ model: {
+ props: 'list',
+ events: 'update'
+ }
+ }
+ `,
+ errors: [
+ "Invalid key 'props' in model option.",
+ "Invalid key 'events' in model option."
+ ]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+ export default {
+ model: {
+ prop: 'checked',
+ props: 'list',
+ event: 'update'
+ }
+ }
+ `,
+ errors: ["Invalid key 'props' in model option."]
+ },
+ {
+ filename: 'test.vue',
+ code: `
+ export default {
+ model: {
+ name: 'checked',
+ props: 'list',
+ event: 'update'
+ }
+ }
+ `,
+ errors: [
+ "Invalid key 'name' in model option.",
+ "Invalid key 'props' in model option."
+ ]
+ }
+ ]
+})