Skip to content
NewBun 1.4.5 is out. Release notes
AphrodyBun

Linter · Rules

@typescript-eslint/no-redeclare

Disallow declaring the same name twice in one scope

var lets you declare a name a second time without an error. The second declaration is the same variable as the first, so it overwrites a value that other code may still need. It's usually a copy and paste mistake, or two parts of a long function that picked the same name.

This is no-redeclare for TypeScript. It knows about function overloads and the declarations TypeScript merges on purpose, such as two interfaces with the same name.

With bunfig.toml you can set either name. bun lint runs this rule in TypeScript files and no-redeclare in JavaScript files, so nothing is reported twice. With an ESLint config, use it in place of no-redeclare, which reports those.

Configure

Off by default. To turn it on:

bunfig.toml
[lint.rules]
"@typescript-eslint/no-redeclare" = "error" # or "warn"

Every option, set to its default:

bunfig.toml
[lint.rules]
"@typescript-eslint/no-redeclare" = ["error", {
  builtinGlobals = true,
  ignoreDeclarationMerge = true,
}]

Examples

Reported:

function price(items: number[]) {
  var total = items.length;
  for (const item of items) {
    var total = item;
  }
  return total;
}

Not reported:

function price(items: number[]) {
  let total = items.length;
  for (const item of items) {
    total += item;
  }
  return total;
}

Overloads and merged declarations aren't reported either:

function parse(input: string): number;
function parse(input: number): number;
function parse(input: string | number) {
  return Number(input);
}

interface Options {
  verbose: boolean;
}
interface Options {
  color: boolean;
}

class Logger {}
namespace Logger {
  export const level = "info";
}

Options

OptionDefaultWhat it does
builtinGlobalstrueAlso report a name that's already a global, such as Object. This applies to the top level of a script and to /* global */ comments. The top level of a module is its own scope.
ignoreDeclarationMergetrueAllow the declarations TypeScript merges: interfaces with interfaces, namespaces with namespaces, and one class, function or enum with namespaces. A class also merges with interfaces.

Reported by default, and allowed with builtinGlobals: false:

/* global process */

console.log(process.platform);
/* global process */

console.log(process.platform);

Reported with ignoreDeclarationMerge: false:

interface Options {
  verbose: boolean;
}
interface Options {
  color: boolean;
}

Two enums with the same name are always reported:

enum Level {
  Info,
}
enum Level {
  Error = 1,
}