denoland / deno_lint

Blazing fast linter for JavaScript and TypeScript written in Rust
https://lint.deno.land/
MIT License
1.53k stars 172 forks source link

Interface with no members but with `extend` is not equivalent of the supertype #1249

Closed Im-Beast closed 6 months ago

Im-Beast commented 7 months ago

An interface that extends, but has no members isn't equivalent of the supertype when interface has been already declared.

Stated by the lint description:

An interface declaring no members is equivalent to its supertype. Use the supertype instead, or add members to this interface.

It is in fact not true, since interface ABC extends XYZ {} extends the existing ABC interface by the members of XYZ. And in case of the interface being defined for the first time, the same applies – it can be later extended with other interface declarations, where type cannot.

Lint Name

no-empty-interface

Code Snippet

interface ABC {
  abc: true;
}

interface XYZ {
  xyz: true;
}

interface ABC extends XYZ {}; // deno-lint(no-empty-interface)

TypeEquals<ABC, {
  abc: true;
  xyz: true;
}>;
type MappedType = {
  [thing in "a" | "b" | "c"]: true;
};

interface ABC extends MappedType {}; // workaround around not being able to use mapped types in interfaces. This allows `ABC` to be extended with other interface declarations.

interface ABC {
  abc: true;
}

TypeEquals<ABC, {
  abc: true;
  a: true;
  b: true;
  c: true;
}>;

Expected Result

Actual Result

Additional Info

interface ABC extends XYZ {} can be useful in scenarios, where global namespaces are augmented to allow extending given type definitions by the module.

Version

deno 1.40.4 (release, x86_64-unknown-linux-gnu)
v8 12.1.285.6
typescript 5.3.3