7

My understanding is destructuring like this will pick properties from the incoming argument object:

const last = "Smith" // unrelated const

const full = function({ first, last }) {
  return [first, last].filter(v => v).join(" ")
}

full({last: "Doe"}) // "Doe"
full({}) // ""

And this seems to work the same for imports.

import last from "last"; // unrelated import

export function full({ first, last }) {
  return [first, last].filter(v => v).join(" ")
}

full({last: "Doe"}) // "Doe"
full({}) // ""

Why then does this cause a no-shadow eslint error?

error 'last' is already declared in the upper scope no-shadow

Is there any circumstance where full could have access to the outer reference? No, right? How might I keep syntax close to this without renaming the unrelated outer last reference?

ryanve
  • 50,076
  • 30
  • 102
  • 137
  • Uh, if you don't need the reference to the outer variable and *want to use shadowing*, then you shouldn't enable that eslint rule?! – Bergi Jun 08 '17 at 20:49
  • The problem has nothing to do with destructuring... you are declaring a variable with the same name as an "outer" variable. If eslint is configured to complain about that then it will. You can disable that rule if you don't want that. – Felix Kling Jun 08 '17 at 22:13
  • This is related https://stackoverflow.com/questions/37682705/avoid-no-shadow-eslint-error-with-mapdispatchtoprops – frederj Dec 11 '19 at 16:25

1 Answers1

8

It's causing an eslint error because last is declared in the import and in the the function as an argument. So inside the function, the argument last is shadowing the import last. You simply need to change the name of the parameter inside the function or turn eslint off.

import last from "last"; // unrelated import

export function full({ first, last: lst }) {
  return [first, lst].filter(v => v).join(" ")
}

full({last: "Doe"}) // "Doe"
full({}) // ""

...or...

import last from "last"; // unrelated import

export function full({ first, last }) { // eslint-disable-line no-shadow
  return [first, last].filter(v => v).join(" ")
}

full({last: "Doe"}) // "Doe"
full({}) // ""
searsaw
  • 3,492
  • 24
  • 31
  • Isn't that the normal way that JavaScript scoping works? Why should that cause an error? – ryanve Jun 08 '17 at 20:42
  • 5
    It's only an error because eslint was told to flag it as an error. That is entirely valid JS syntax. However, it can cause subtle issues if the developer doesn't realize they shadowed a variable. So you can have eslint complain about it so you can avoid potential hard to track down bugs. – searsaw Jun 08 '17 at 20:46
  • 1
    Thanks :) Makes sense. I ended up renaming the outer reference because the inner one was for the values from the API. – ryanve Jun 10 '17 at 20:51
  • the second solution will work for sure, but it is not ideal case, and the first one will trigger `(no-unused-vars)`. so is this a bug? – Seeliang Aug 02 '18 at 11:58