diff --git a/lib/rules/no-undef-components.js b/lib/rules/no-undef-components.js
index dc58fd2e9..3ffe9cc3b 100644
--- a/lib/rules/no-undef-components.js
+++ b/lib/rules/no-undef-components.js
@@ -133,7 +133,29 @@ module.exports = {
(scope) => scope.type === 'module'
)
for (const variable of (moduleScope && moduleScope.variables) || []) {
- if (variable.isTypeVariable) {
+ if (
+ // Check for type definitions. e.g. type Foo = {}
+ (variable.isTypeVariable && !variable.isValueVariable) ||
+ // type-only import seems to have isValueVariable set to true. So we need to check the actual Node.
+ (variable.defs.length > 0 &&
+ variable.defs.every((def) => {
+ if (def.type !== 'ImportBinding') {
+ return false
+ }
+ if (def.parent.importKind === 'type') {
+ // check for `import type Foo from './xxx'`
+ return true
+ }
+ if (
+ def.node.type === 'ImportSpecifier' &&
+ def.node.importKind === 'type'
+ ) {
+ // check for `import { type Foo } from './xxx'`
+ return true
+ }
+ return false
+ }))
+ ) {
scriptTypeOnlyNames.add(variable.name)
} else {
scriptVariableNames.add(variable.name)
diff --git a/tests/lib/rules/no-undef-components.js b/tests/lib/rules/no-undef-components.js
index fc3461e5a..5af9468fe 100644
--- a/tests/lib/rules/no-undef-components.js
+++ b/tests/lib/rules/no-undef-components.js
@@ -6,6 +6,7 @@
const RuleTester = require('eslint').RuleTester
const rule = require('../../../lib/rules/no-undef-components')
+const semver = require('semver')
const tester = new RuleTester({
parser: require.resolve('vue-eslint-parser'),
@@ -598,6 +599,26 @@ tester.run('no-undef-components', rule, {
`
+ },
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
+
+
+ `,
+ parserOptions: {
+ ecmaVersion: 6,
+ sourceType: 'module',
+ parser: require.resolve('@typescript-eslint/parser')
+ },
+ parser: require.resolve('vue-eslint-parser')
}
],
invalid: [
@@ -661,9 +682,14 @@ tester.run('no-undef-components', rule, {
}
]
},
- {
- filename: 'test.vue',
- code: `
+ ...(semver.gte(
+ require('@typescript-eslint/parser/package.json').version,
+ '5.0.0'
+ )
+ ? [
+ {
+ filename: 'test.vue',
+ code: `
+
+
+
+
`,
parserOptions: {
ecmaVersion: 6,
@@ -692,32 +770,7 @@ tester.run('no-undef-components', rule, {
{
message:
"The '' component has been used, but 'Foo' only refers to a type.",
- line: 12
- },
- {
- message:
- "The '' component has been used, but 'HelloWorld1' only refers to a type.",
- line: 13
- },
- {
- message:
- "The '' component has been used, but 'HelloWorld2' only refers to a type.",
- line: 14
- },
- {
- message:
- "The '' component has been used, but 'HelloWorld3' only refers to a type.",
- line: 15
- },
- {
- message:
- "The '' component has been used, but 'HelloWorld4' only refers to a type.",
- line: 16
- },
- {
- message:
- "The '' component has been used, but 'HelloWorld5' only refers to a type.",
- line: 17
+ line: 7
}
]
},
diff --git a/typings/eslint-plugin-vue/util-types/ast/es-ast.ts b/typings/eslint-plugin-vue/util-types/ast/es-ast.ts
index f4dd208c3..b3d5b6e2e 100644
--- a/typings/eslint-plugin-vue/util-types/ast/es-ast.ts
+++ b/typings/eslint-plugin-vue/util-types/ast/es-ast.ts
@@ -274,6 +274,7 @@ export interface ImportSpecifier extends HasParentNode {
type: 'ImportSpecifier'
imported: Identifier
local: Identifier
+ importKind?: 'type' | 'value'
}
export interface ImportDefaultSpecifier extends HasParentNode {
type: 'ImportDefaultSpecifier'