Skip to content

Commit aa0d842

Browse files
authored
chore(lint): enforce use of type-only imports (#5658)
1 parent 39eb65c commit aa0d842

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

packages/typescript-plugin/lib/requests/getReactiveReferences.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createProxyLanguageService, decorateLanguageServiceHost } from '@volar/typescript';
2-
import { type Language, type SourceScript } from '@vue/language-core';
2+
import type { Language, SourceScript } from '@vue/language-core';
33
import { createAnalyzer } from 'laplacenoma';
44
import * as rulesVue from 'laplacenoma/rules/vue';
55
import type * as ts from 'typescript';

tsslint.config.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,52 @@ export default defineConfig({
150150
ts.forEachChild(node, visit);
151151
});
152152
},
153+
'type-imports'({ typescript: ts, file, report }) {
154+
ts.forEachChild(file, function visit(node) {
155+
if (
156+
ts.isImportDeclaration(node)
157+
&& node.importClause
158+
&& node.importClause.namedBindings
159+
&& node.importClause.phaseModifier !== ts.SyntaxKind.TypeKeyword
160+
&& !node.importClause.name
161+
&& !ts.isNamespaceImport(node.importClause.namedBindings)
162+
&& node.importClause.namedBindings.elements.every(e => e.isTypeOnly)
163+
) {
164+
const typeElements = node.importClause.namedBindings.elements;
165+
report(
166+
'This import statement should use type-only import.',
167+
node.getStart(file),
168+
node.getEnd(),
169+
).withFix(
170+
'Replace inline type imports with a type-only import.',
171+
() => [
172+
{
173+
fileName: file.fileName,
174+
textChanges: [
175+
...typeElements.map(element => {
176+
const token = element.getFirstToken(file)!;
177+
return {
178+
newText: '',
179+
span: {
180+
start: token.getStart(file),
181+
length: element.name.getStart(file) - token.getStart(file),
182+
},
183+
};
184+
}),
185+
{
186+
newText: 'type ',
187+
span: {
188+
start: node.importClause!.getStart(file),
189+
length: 0,
190+
},
191+
},
192+
],
193+
},
194+
],
195+
);
196+
}
197+
ts.forEachChild(node, visit);
198+
});
199+
},
153200
},
154201
});

0 commit comments

Comments
 (0)