Blog post

Common TypeScript Issues Nº 3: unused local variables and functions

Blog Author Phil Nash

Phil Nash

Developer Advocate JS/TS

5 min read

  • SonarLint
  • TypeScript
  • JavaScript
  • ESLint

We're counting down the top 5 issues that SonarLint sees in all of our TypeScript, describing the issues and how to fix, or even better, avoid them.


You can play with these issues yourself by installing SonarLint in your editor and copy-pasting the example code below. This issue also counts for JavaScript, there's nothing special about TypeScript here.

Nº 3: unused local variables and functions

This is probably not a surprise. Every time you're in your editor and you write a new variable tooling like SonarLint swings in to tell you that your variable is unused. You know it's unused because you haven't used it yet.

function sayHello(name: string) {
  const greeting = "Hello";
  // I just haven’t written the part that uses the greeting with the name yet!
}

Issues like this are easy to fix, you keep writing the code you were intending to and use the variable that you defined. But there are plenty of reasons you might end up with unused variables that can cause problems.


As you write and refactor code, variables, and functions you thought you needed can become redundant. It's hard to keep track of every variable and function you write in your head so it's easy to leave them in a codebase and really useful when your tooling highlights it for you.


So what are the issues that unused variables or functions can cause?


The first relates to the readability of your code. If you delete old code but leave unused variables or functions lying around, the next time someone comes to read that code they will have to spend time working out whether those variables or functions are needed for something.


Next, if you are writing TypeScript or JavaScript for the front-end then every unused variable or function that remains in your codebase is just extra bytes you have to send over the wire to your users. Unused code bloats your codebase unnecessarily and impacts the performance of your application.


One interesting instance of unused variables I spotted in the wild looked like this:

const [_, params] = url.split(path);

Naming a variable that is unused with an underscore, or prefixing a variable name with an underscore, are conventions to show other developers that we had to name the variable, but we don't intend to use it. In this case, you don't need to name the variable though. You can actually ignore values in your destructuring assignment and just name the variables you want to assign to. So the above can be rewritten as:

const [, params] = url.split(path);

Now the code won't make an unnecessary assignment and trigger this linting rule.

What about bugs?

I believe in Clean Code, so not leaving extra bloat in a codebase and making things easier to read is important. The question is, can unused variables and functions actually cause bugs? 


Of course they can!


Enter the following code in your editor:

function doSomething(start: number, stop: number) {
  // does something between start and stop
}

function init() {
  const start = 1;
  const stop = 10;
  doSomething(start, start);
}

You will see that stop is unused. This highlights a human error, passing start as both arguments to the doSomething function when the second argument should have been stop. Probably a result of hitting tab to autocomplete and the editor completing start instead of stop. An easy mistake to make, but one caught by this rule.

Memory leaks

Unused functions can also help to cause memory leaks. A real issue cropped up in the Meteor framework a few years ago. David Glasser wrote up what had happened, explaining exactly how an unused function caused a closure over a variable that should have otherwise been released to the garbage collector. I recommend you read the entire article for all the details. The final example code, in JavaScript in this case, was as follows:

let theThing = null;
const replaceThing = function () {
  const originalThing = theThing;
  const unused = function () {
    if (originalThing) {
      console.log("hi");
    }
  };
  theThing = {
    longStr: new Array(1000000).join("*"),
    someMethod: function () {
      console.log(someMessage);
    },
  };
};
setInterval(replaceThing, 1000);

Copy the code and paste it into your editor and you will find that the function unused is highlighted as an unused function. The fact that unused refers to originalThing within the function body means that the garbage collector is unable to reclaim the memory used to store originalThing and so the memory usage of the application just grows over time. The investigation and fix for Meteor were a bit more complicated, but this example shows how even an unused function can cause issues in an application.

Poor readability, unnecessary code bloat, human error, and even memory leaks are all potential outcomes of an unused variable or function. That's why SonarLint enforces the rule that unused local variables and functions should be removed.

Use 'em or lose 'em

Removing or fixing unused variables and functions is a surefire way to keep your code clean and avoid potential problems. And it's a common enough problem to come in at number 3 in our countdown of the most common TypeScript issues.


Next up is the second most common issue seen in SonarLint. Any guesses? Share them in the community or with @SonarSource on Twitter.


So far in our Top 5 countdown:


No.4 Dropping and creating objects

No.5 Optional property declarations


Free Video! Best practices to improve your JavaScript coding.
Watch now