Duplicate String Literals

ID

javascript.duplicate_string_literals

Severity

high

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Code Smell

Language

JavaScript

Tags

code-style, duplication

Description

Reports a string literal that appears the same three or more times in one file. The thresholds are configurable: minOccurrences (3 by default) and minLength (5), since short strings like "," or "id" are rarely worth constantising.

The scope is the file, not the class — a JavaScript module is the unit that holds its own constants, and most modules are a set of top-level functions with no class at all. One finding per file and literal, at the first occurrence, with the literal named in the message.

Only literals in expression position are counted. A module specifier, an object-literal key and a JSX string attribute (className="row") are the same text in a place where it is not a magic value, and none of them is counted. Neither are literals inside an array literal, or inside a decorator.

Rationale

// Bad
function reportError(kind) {
  if (kind === "connection-failed") {
    notify("connection-failed");
    return true;
  }
  return kind === "connection-failed";
}
  • The three copies are meant to stay in step, and nothing in the code says so. Renaming the event to connection-lost in two of the three places is a bug that no compiler, type checker or test of the happy path will catch.

  • A typo in one copy produces a comparison that is simply never true. The === still type-checks, the branch just goes dead.

  • A named constant also gives the value somewhere to be documented, and makes it greppable as one symbol rather than as a quoted string that may or may not be the same one.

The exclusions are all cases where the repetition is not a coupling. A keyword list, a MIME-type table or a locale map repeats a word because several rows genuinely share it — "extract it to a constant" is not advice that can be followed there. A decorator argument is configuration DSL. A repeated import path is the concern of javascript.duplicate_imports. And a spec file repeats a fixture name across cases on purpose: the repetition is what makes each case readable on its own, so test files are skipped whole.

Remediation

Extract the value into a module-level constant and use it everywhere.

// Good
const CONNECTION_FAILED = "connection-failed";

function reportError(kind) {
  if (kind === CONNECTION_FAILED) {
    notify(CONNECTION_FAILED);
    return true;
  }
  return kind === CONNECTION_FAILED;
}

When the value is one of a closed set, a frozen map of them reads better still and gives the set a name:

const ErrorKind = Object.freeze({
  CONNECTION_FAILED: "connection-failed",
  TIMED_OUT: "timed-out",
});

© 2026 Xygeni. All rights reserved