diff --git a/lib/rules/valid-v-model.js b/lib/rules/valid-v-model.js index 2378c86f2..d818439bd 100644 --- a/lib/rules/valid-v-model.js +++ b/lib/rules/valid-v-model.js @@ -49,6 +49,10 @@ function isOptionalChainingMemberExpression(node) { * @returns {boolean} `true` if the node can be LHS. */ function isLhs(node) { + if (node.type === 'TSAsExpression' || node.type === 'TSNonNullExpression') { + return isLhs(node.expression) + } + return node.type === 'Identifier' || node.type === 'MemberExpression' } diff --git a/tests/lib/rules/valid-v-model.js b/tests/lib/rules/valid-v-model.js index 38b4ae175..02264e527 100644 --- a/tests/lib/rules/valid-v-model.js +++ b/tests/lib/rules/valid-v-model.js @@ -143,6 +143,51 @@ tester.run('valid-v-model', rule, { { filename: 'comment-value.vue', code: '' + }, + { + filename: 'test.vue', + code: '', + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } + }, + { + filename: 'test.vue', + code: '', + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } + }, + { + filename: 'test.vue', + code: '', + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } + }, + { + filename: 'test.vue', + code: '', + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } + }, + { + filename: 'test.vue', + code: '', + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } } ], invalid: [ @@ -241,6 +286,66 @@ tester.run('valid-v-model', rule, { filename: 'test.vue', code: '', errors: ["'v-model' directive has potential null object property access."] + }, + { + filename: 'test.vue', + code: '', + errors: [ + "'v-model' directives require the attribute value which is valid as LHS." + ], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } + }, + { + filename: 'test.vue', + code: '', + errors: [ + "'v-model' directives require the attribute value which is valid as LHS." + ], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } + }, + { + filename: 'test.vue', + code: '', + errors: [ + "'v-model' directives require the attribute value which is valid as LHS." + ], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } + }, + { + filename: 'test.vue', + code: '', + errors: [ + "'v-model' directives require the attribute value which is valid as LHS." + ], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } + }, + { + filename: 'test.vue', + code: '', + errors: [ + "'v-model' directives require the attribute value which is valid as LHS." + ], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } } ] }) diff --git a/typings/eslint-plugin-vue/util-types/ast/ts-ast.ts b/typings/eslint-plugin-vue/util-types/ast/ts-ast.ts index e3c5f0faf..fec18e9e8 100644 --- a/typings/eslint-plugin-vue/util-types/ast/ts-ast.ts +++ b/typings/eslint-plugin-vue/util-types/ast/ts-ast.ts @@ -6,6 +6,7 @@ import * as ES from './es-ast' import { TSESTree } from '@typescript-eslint/types' export type TSNode = | TSAsExpression + | TSNonNullExpression | TSTypeParameterInstantiation | TSPropertySignature | TSMethodSignatureBase @@ -20,6 +21,11 @@ export interface TSAsExpression extends HasParentNode { typeAnnotation: any } +export interface TSNonNullExpression extends HasParentNode { + type: 'TSNonNullExpression' + expression: ES.Expression +} + export interface TSTypeParameterInstantiation extends HasParentNode { type: 'TSTypeParameterInstantiation' params: TypeNode[]