Skip to content

Commit 991f0ca

Browse files
committed
extensions: add the checkTypeImports option
1 parent 88dd815 commit 991f0ca

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

docs/rules/extensions.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ For example, `["error", "never", { "svg": "always" }]` would require that all ex
5656
In that case, if you still want to specify extensions, you can do so inside the **pattern** property.
5757
Default value of `ignorePackages` is `false`.
5858

59+
By default, `import type` and `export type` style imports/exports are ignored. If you want to check them as well, you can set the `checkTypeImports` option to `true`.
60+
5961
### Exception
6062

6163
When disallowing the use of certain extensions this rule makes an exception and allows the use of extension when the file would not be resolvable without extension.
@@ -167,6 +169,14 @@ import express from 'express';
167169
import foo from '@/foo';
168170
```
169171

172+
The following patterns are considered problems when the option "checkTypeImports" is set to `true`:
173+
174+
```js
175+
import type { Foo } from './foo';
176+
177+
export type { Foo } from './foo';
178+
```
179+
170180
## When Not To Use It
171181

172182
If you are not concerned about a consistent usage of file extension.

src/rules/extensions.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const properties = {
1414
type: 'object',
1515
properties: {
1616
pattern: patternProperties,
17+
checkTypeImports: { type: 'boolean' },
1718
ignorePackages: { type: 'boolean' },
1819
},
1920
};
@@ -35,7 +36,7 @@ function buildProperties(context) {
3536
}
3637

3738
// If this is not the new structure, transfer all props to result.pattern
38-
if (obj.pattern === undefined && obj.ignorePackages === undefined) {
39+
if (obj.pattern === undefined && obj.ignorePackages === undefined && obj.checkTypeImports === undefined) {
3940
Object.assign(result.pattern, obj);
4041
return;
4142
}
@@ -49,6 +50,10 @@ function buildProperties(context) {
4950
if (obj.ignorePackages !== undefined) {
5051
result.ignorePackages = obj.ignorePackages;
5152
}
53+
54+
if (obj.checkTypeImports !== undefined) {
55+
result.checkTypeImports = obj.checkTypeImports;
56+
}
5257
});
5358

5459
if (result.defaultConfig === 'ignorePackages') {
@@ -167,7 +172,7 @@ module.exports = {
167172

168173
if (!extension || !importPath.endsWith(`.${extension}`)) {
169174
// ignore type-only imports and exports
170-
if (node.importKind === 'type' || node.exportKind === 'type') { return; }
175+
if (props.checkTypeImports !== true && (node.importKind === 'type' || node.exportKind === 'type')) { return; }
171176
const extensionRequired = isUseOfExtensionRequired(extension, isPackage);
172177
const extensionForbidden = isUseOfExtensionForbidden(extension);
173178
if (extensionRequired && !extensionForbidden) {

tests/src/rules/extensions.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,24 @@ describe('TypeScript', () => {
640640
],
641641
parser,
642642
}),
643+
test({
644+
code: 'import type T from "./typescript-declare";',
645+
errors: ['Missing file extension for "./typescript-declare"'],
646+
options: [
647+
'always',
648+
{ ts: 'never', tsx: 'never', js: 'never', jsx: 'never', checkTypeImports: true },
649+
],
650+
parser,
651+
}),
652+
test({
653+
code: 'export type { MyType } from "./typescript-declare";',
654+
errors: ['Missing file extension for "./typescript-declare"'],
655+
options: [
656+
'always',
657+
{ ts: 'never', tsx: 'never', js: 'never', jsx: 'never', checkTypeImports: true },
658+
],
659+
parser,
660+
}),
643661
],
644662
});
645663
});

0 commit comments

Comments
 (0)