A file with no import and no export is valid both as a script and as a module, and the two run differently. A module is in strict mode, its top-level this is undefined, and its top-level declarations aren't global. A tool that has to guess from the content can guess wrong.
One import or export statement settles it. import(), import.meta, top-level await and require() don't count.
Configure
Off by default. To turn it on:
[lint.rules]
"import/unambiguous" = "error" # or "warn"
Examples
Reported:
function greet(name) {
console.log(`Hello, ${name}`);
}
greet("Ada");
const { greet } = await import("./greet.js");
greet("Ada");
Not reported:
export function greet(name) {
console.log(`Hello, ${name}`);
}
If the file has nothing to export, an empty export marks it as a module:
function greet(name) {
console.log(`Hello, ${name}`);
}
greet("Ada");
export {};
A .cjs file is never a module, so it isn't checked:
console.log("Hello, Ada");
When not to use it
If every tool you use decides by the file extension or by "type" in package.json, the file's content doesn't matter and this rule is noise.