diff --git a/lib/rules/valid-define-emits.js b/lib/rules/valid-define-emits.js
index 1fabbc025..b16fc300e 100644
--- a/lib/rules/valid-define-emits.js
+++ b/lib/rules/valid-define-emits.js
@@ -85,6 +85,9 @@ module.exports = {
!utils.inRange(defineEmits.range, def.name)
)
) {
+ if (utils.withinTypeNode(node)) {
+ continue
+ }
//`defineEmits` are referencing locally declared variables.
context.report({
node,
diff --git a/lib/rules/valid-define-props.js b/lib/rules/valid-define-props.js
index b67af7c8c..273eae70a 100644
--- a/lib/rules/valid-define-props.js
+++ b/lib/rules/valid-define-props.js
@@ -86,6 +86,9 @@ module.exports = {
!utils.inRange(defineProps.range, def.name)
)
) {
+ if (utils.withinTypeNode(node)) {
+ continue
+ }
//`defineProps` are referencing locally declared variables.
context.report({
node,
diff --git a/lib/utils/indent-ts.js b/lib/utils/indent-ts.js
index ed2080750..b98e9d105 100644
--- a/lib/utils/indent-ts.js
+++ b/lib/utils/indent-ts.js
@@ -12,6 +12,7 @@ const {
isClosingBracketToken,
isOpeningBracketToken
} = require('eslint-utils')
+const { isTypeNode } = require('./ts-ast-utils')
/**
* @typedef {import('../../typings/eslint-plugin-vue/util-types/indent-helper').TSNodeListener} TSNodeListener
@@ -224,46 +225,9 @@ function defineVisitor({
*/
// eslint-disable-next-line complexity -- ignore
'*[type=/^TS/]'(node) {
- if (
- node.type !== 'TSAnyKeyword' &&
- node.type !== 'TSArrayType' &&
- node.type !== 'TSBigIntKeyword' &&
- node.type !== 'TSBooleanKeyword' &&
- node.type !== 'TSConditionalType' &&
- node.type !== 'TSConstructorType' &&
- node.type !== 'TSFunctionType' &&
- node.type !== 'TSImportType' &&
- node.type !== 'TSIndexedAccessType' &&
- node.type !== 'TSInferType' &&
- node.type !== 'TSIntersectionType' &&
- node.type !== 'TSIntrinsicKeyword' &&
- node.type !== 'TSLiteralType' &&
- node.type !== 'TSMappedType' &&
- node.type !== 'TSNamedTupleMember' &&
- node.type !== 'TSNeverKeyword' &&
- node.type !== 'TSNullKeyword' &&
- node.type !== 'TSNumberKeyword' &&
- node.type !== 'TSObjectKeyword' &&
- node.type !== 'TSOptionalType' &&
- node.type !== 'TSRestType' &&
- node.type !== 'TSStringKeyword' &&
- node.type !== 'TSSymbolKeyword' &&
- node.type !== 'TSTemplateLiteralType' &&
- node.type !== 'TSThisType' &&
- node.type !== 'TSTupleType' &&
- node.type !== 'TSTypeLiteral' &&
- node.type !== 'TSTypeOperator' &&
- node.type !== 'TSTypePredicate' &&
- node.type !== 'TSTypeQuery' &&
- node.type !== 'TSTypeReference' &&
- node.type !== 'TSUndefinedKeyword' &&
- node.type !== 'TSUnionType' &&
- node.type !== 'TSUnknownKeyword' &&
- node.type !== 'TSVoidKeyword'
- ) {
+ if (!isTypeNode(node)) {
return
}
- /** @type {TypeNode} */
const typeNode = node
if (/** @type {any} */ (typeNode.parent).type === 'TSParenthesizedType') {
return
diff --git a/lib/utils/index.js b/lib/utils/index.js
index 36614cd14..5c49d15f2 100644
--- a/lib/utils/index.js
+++ b/lib/utils/index.js
@@ -54,7 +54,8 @@ const { traverseNodes, getFallbackKeys } = vueEslintParser.AST
const { findVariable } = require('eslint-utils')
const {
getComponentPropsFromTypeDefine,
- getComponentEmitsFromTypeDefine
+ getComponentEmitsFromTypeDefine,
+ isTypeNode
} = require('./ts-ast-utils')
/**
@@ -1717,6 +1718,10 @@ module.exports = {
* Retrieve `ChainExpression#expression` value if the given node a `ChainExpression` node. Otherwise, pass through it.
*/
skipChainExpression,
+ /**
+ * Checks whether the given node is in a type annotation.
+ */
+ withinTypeNode,
findVariableByIdentifier,
getScope,
/**
@@ -2226,6 +2231,23 @@ function skipChainExpression(node) {
return node
}
+/**
+ * Checks whether the given node is in a type annotation.
+ * @param {ESNode} node
+ * @returns {boolean}
+ */
+function withinTypeNode(node) {
+ /** @type {ASTNode | null} */
+ let target = node
+ while (target) {
+ if (isTypeNode(target)) {
+ return true
+ }
+ target = target.parent
+ }
+ return false
+}
+
/**
* Gets the property name of a given node.
* @param {Property|AssignmentProperty|MethodDefinition|MemberExpression} node - The node to get.
diff --git a/lib/utils/ts-ast-utils.js b/lib/utils/ts-ast-utils.js
index b801b6374..6777859b8 100644
--- a/lib/utils/ts-ast-utils.js
+++ b/lib/utils/ts-ast-utils.js
@@ -4,6 +4,7 @@ const { findVariable } = require('eslint-utils')
* @typedef {import('@typescript-eslint/types').TSESTree.TSInterfaceBody} TSInterfaceBody
* @typedef {import('@typescript-eslint/types').TSESTree.TSTypeLiteral} TSTypeLiteral
* @typedef {import('@typescript-eslint/types').TSESTree.Parameter} TSESTreeParameter
+ * @typedef {import('@typescript-eslint/types').TSESTree.Node} Node
*
*/
/**
@@ -12,10 +13,55 @@ const { findVariable } = require('eslint-utils')
*/
module.exports = {
+ isTypeNode,
getComponentPropsFromTypeDefine,
getComponentEmitsFromTypeDefine
}
+/**
+ * @param {Node | ASTNode} node
+ * @returns {node is TypeNode}
+ */
+function isTypeNode(node) {
+ return (
+ node.type === 'TSAnyKeyword' ||
+ node.type === 'TSArrayType' ||
+ node.type === 'TSBigIntKeyword' ||
+ node.type === 'TSBooleanKeyword' ||
+ node.type === 'TSConditionalType' ||
+ node.type === 'TSConstructorType' ||
+ node.type === 'TSFunctionType' ||
+ node.type === 'TSImportType' ||
+ node.type === 'TSIndexedAccessType' ||
+ node.type === 'TSInferType' ||
+ node.type === 'TSIntersectionType' ||
+ node.type === 'TSIntrinsicKeyword' ||
+ node.type === 'TSLiteralType' ||
+ node.type === 'TSMappedType' ||
+ node.type === 'TSNamedTupleMember' ||
+ node.type === 'TSNeverKeyword' ||
+ node.type === 'TSNullKeyword' ||
+ node.type === 'TSNumberKeyword' ||
+ node.type === 'TSObjectKeyword' ||
+ node.type === 'TSOptionalType' ||
+ node.type === 'TSRestType' ||
+ node.type === 'TSStringKeyword' ||
+ node.type === 'TSSymbolKeyword' ||
+ node.type === 'TSTemplateLiteralType' ||
+ node.type === 'TSThisType' ||
+ node.type === 'TSTupleType' ||
+ node.type === 'TSTypeLiteral' ||
+ node.type === 'TSTypeOperator' ||
+ node.type === 'TSTypePredicate' ||
+ node.type === 'TSTypeQuery' ||
+ node.type === 'TSTypeReference' ||
+ node.type === 'TSUndefinedKeyword' ||
+ node.type === 'TSUnionType' ||
+ node.type === 'TSUnknownKeyword' ||
+ node.type === 'TSVoidKeyword'
+ )
+}
+
/**
* @param {TypeNode} node
* @returns {node is TSTypeLiteral}
diff --git a/tests/lib/rules/valid-define-emits.js b/tests/lib/rules/valid-define-emits.js
index 542805848..557101d67 100644
--- a/tests/lib/rules/valid-define-emits.js
+++ b/tests/lib/rules/valid-define-emits.js
@@ -73,6 +73,50 @@ tester.run('valid-define-emits', rule, {
})
`
+ },
+ {
+ // https://github.com/vuejs/eslint-plugin-vue/issues/1656
+ filename: 'test.vue',
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ },
+ code: `
+
+ `
+ },
+ {
+ filename: 'test.vue',
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ },
+ code: `
+
+ `
}
],
invalid: [
diff --git a/tests/lib/rules/valid-define-props.js b/tests/lib/rules/valid-define-props.js
index cb1f50daf..10894e069 100644
--- a/tests/lib/rules/valid-define-props.js
+++ b/tests/lib/rules/valid-define-props.js
@@ -76,6 +76,50 @@ tester.run('valid-define-props', rule, {
})
`
+ },
+ {
+ // https://github.com/vuejs/eslint-plugin-vue/issues/1656
+ filename: 'test.vue',
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ },
+ code: `
+
+ `
+ },
+ {
+ filename: 'test.vue',
+ parserOptions: {
+ parser: require.resolve('@typescript-eslint/parser')
+ },
+ code: `
+
+ `
}
],
invalid: [