Description
v2.32.0
I've seen some issues filed about no-duplicates and type imports, but they appear different from what I'm currently seeing in version 2.32.0.
no-duplicates rule code in question
function getImportMap(n) {
if (!moduleMaps.has(n.parent)) {
moduleMaps.set(n.parent, /** @type {typeof moduleMaps} */ {
imported: new Map(),
nsImported: new Map(),
defaultTypesImported: new Map(),
namedTypesImported: new Map(),
});
}
const map = moduleMaps.get(n.parent);
if (!preferInline && n.importKind === 'type') {
return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? map.defaultTypesImported : map.namedTypesImported;
}
if (!preferInline && n.specifiers.some((spec) => spec.importKind === 'type')) {
return map.namedTypesImported;
}
return hasNamespace(n) ? map.nsImported : map.imported;
}
1. Namespace type imports are grouped with named type imports when prefer-inline
is off.
With prefer-inline
off, an error is shown for the following code, but the error disappears when turning on prefer-inline
.
import type * as React from "react";
import { type ReactElement } from "react";
If anything, that would be backwards, but really, these two lines can never be combined. The problem comes from this block in the rule code:
if (!preferInline && n.importKind === 'type') {
return n.specifiers.length > 0 && n.specifiers[0].type === 'ImportDefaultSpecifier' ? map.defaultTypesImported : map.namedTypesImported;
}
This block says if we're dealing with a type import, it's either a default import or a named import, but that's not true — it could also be a namespace import, which similarly can't be combined with named imports.
2. Default type imports are grouped with named type imports when prefer-inline
is on
With prefer-inline
on, an error is shown for the following code:
import type React from "react";
import { type ReactElement } from "react";
But attempting to combine them into a single line yields the following TypeScript error:
A type-only import can specify a default import or named bindings, but not both.
This problem is caused by this line from the rule source:
return hasNamespace(n) ? map.nsImported : map.imported;
It says if prefer-inline is on (meaning previous if
blocks are skipped), the only two groups are namespace imports and not, but this doesn't work for default type imports, which must be separated from named type imports.